All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 01/19] OvmfPkg: Add the MIT license to License.txt.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project Anthony PERARD
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

The MIT license will be used for several source files that are necessary
for the Xen PV drivers. So this patch makes it explicit by adding the
license with a note about which directory will have source files under
this license.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
  New patch
---
 OvmfPkg/License.txt | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/OvmfPkg/License.txt b/OvmfPkg/License.txt
index be68999..e2eff41 100644
--- a/OvmfPkg/License.txt
+++ b/OvmfPkg/License.txt
@@ -23,3 +23,28 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
+
+
+Some files are subject to the following license, the MIT license. Those files
+are located in:
+- OvmfPkg/Include/IndustryStandard/Xen/
+- OvmfPkg/XenBusDxe/
+- OvmfPkg/XenPvBlkDxe/
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
-- 
Anthony PERARD

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

* [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
  2014-10-17 17:03 ` [PATCH v3 01/19] OvmfPkg: Add the MIT license to License.txt Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 03/19] OvmfPkg: Add basic skeleton for the XenBus bus driver Anthony PERARD
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This patch imports publics headers in order to use features from Xen
like XenStore, PV Block... There is only the necessary header files and
there are only a few modifications in order to facilitate future merge of
more recent header (that would be necessary to access new features).

There is little modification compared to the original files:
- Removed most of the unused part of the headers
- Use of ZeroMem() instead of memset()
- using #pragma pack(4) for IA32 compilation.
- Replace types to be more UEFI compliant using a script.

OVMF, when built for IA32 arch, uses the gcc switch -malign-double. This
change the alignment of fields in some struct compare to what is
espected by Xen and any backends. To fix the alignment, the #pragma pack(4)
directive is used around the struct that need it.

Command to run to change types:
find OvmfPkg/Include/IndustryStandard/Xen -type f -name '*.h' -exec sed
  --regexp-extended --file=fix_type_in_xen_includes.sed --in-place {} \;

This line is commented instead of been change as I'm not sure why it
does not compile (when s/char/CHAR8/), and it does not seems necessary
so far.
  /* __DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); */
  in OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h

Avoid changing the 'long' that is not a type (with the first line).
$ cat fix_type_in_xen_includes.sed
/as long as/b

s/([^a-zA-Z0-9_]|^)uint8_t([^a-zA-Z0-9_]|$)/\1UINT8\2/g
s/([^a-zA-Z0-9_]|^)uint16_t([^a-zA-Z0-9_]|$)/\1UINT16\2/g
s/([^a-zA-Z0-9_]|^)uint32_t([^a-zA-Z0-9_]|$)/\1UINT32\2/g
s/([^a-zA-Z0-9_]|^)uint64_t([^a-zA-Z0-9_]|$)/\1UINT64\2/g

s/([^a-zA-Z0-9_]|^)int8_t([^a-zA-Z0-9_]|$)/\1INT8\2/g
s/([^a-zA-Z0-9_]|^)int16_t([^a-zA-Z0-9_]|$)/\1INT16\2/g
s/([^a-zA-Z0-9_]|^)int32_t([^a-zA-Z0-9_]|$)/\1INT32\2/g
s/([^a-zA-Z0-9_]|^)int64_t([^a-zA-Z0-9_]|$)/\1INT64\2/g

s/([^a-zA-Z0-9_]|^)void([^a-zA-Z0-9_]|$)/\1VOID\2/g
s/([^a-zA-Z0-9_]|^)unsigned int([^a-zA-Z0-9_]|$)/\1UINT32\2/g
s/([^a-zA-Z0-9_]|^)int([^a-zA-Z0-9_]|$)/\1INT32\2/g
s/([^a-zA-Z0-9_]|^)char([^a-zA-Z0-9_]|$)/\1CHAR8\2/g
s/([^a-zA-Z0-9_]|^)unsigned long([^a-zA-Z0-9_]|$)/\1UINTN\2/g
s/([^a-zA-Z0-9_]|^)long([^a-zA-Z0-9_]|$)/\1INTN\2/g

License: This patch adds many files under the MIT licence.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- Remove unused header sched.h
- moving xs_wire.h in a later patch, where it's first needed
- moving io/blkif.h in a later patch (XenPvBlkDxe: Add BlockFront client)
- moving event_channel.h in a later patch (XenBusDxe: Add Event Channel Notify)
- using #pragma pack(4) for IA32
- headers trimed down, removed most of the unused struct/define/...
---
 .../IndustryStandard/Xen/arch-x86/xen-x86_32.h     |  59 +++
 .../IndustryStandard/Xen/arch-x86/xen-x86_64.h     |  59 +++
 .../Include/IndustryStandard/Xen/arch-x86/xen.h    | 112 ++++++
 OvmfPkg/Include/IndustryStandard/Xen/grant_table.h | 444 +++++++++++++++++++++
 OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h  |  37 ++
 OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h  | 150 +++++++
 .../Include/IndustryStandard/Xen/io/protocols.h    |  40 ++
 OvmfPkg/Include/IndustryStandard/Xen/io/ring.h     | 312 +++++++++++++++
 OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h   |  80 ++++
 OvmfPkg/Include/IndustryStandard/Xen/memory.h      |  94 +++++
 OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h  |  44 ++
 OvmfPkg/Include/IndustryStandard/Xen/xen.h         | 341 ++++++++++++++++
 12 files changed, 1772 insertions(+)
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/grant_table.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/ring.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/memory.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/xen.h

diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h
new file mode 100644
index 0000000..ed7e12b
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * xen-x86_32.h
+ * 
+ * Guest OS interface to x86 32-bit Xen.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2007, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
+
+/*
+ * Hypercall interface:
+ *  Input:  %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6)
+ *  Output: %eax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ *  call hypercall_page + hypercall-number * 32
+ * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
+ */
+
+#ifndef __ASSEMBLY__
+
+struct arch_vcpu_info {
+    UINTN cr2;
+    UINTN pad[5]; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h
new file mode 100644
index 0000000..c5ef5d4
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ * xen-x86_64.h
+ * 
+ * Guest OS interface to x86 64-bit Xen.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
+
+/*
+ * Hypercall interface:
+ *  Input:  %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
+ *  Output: %rax
+ * Access is via hypercall page (set up by guest loader or via a Xen MSR):
+ *  call hypercall_page + hypercall-number * 32
+ * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
+ */
+
+#ifndef __ASSEMBLY__
+
+struct arch_vcpu_info {
+    UINTN cr2;
+    UINTN pad; /* sizeof(vcpu_info_t) == 64 */
+};
+typedef struct arch_vcpu_info arch_vcpu_info_t;
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
new file mode 100644
index 0000000..951d57b
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
@@ -0,0 +1,112 @@
+/******************************************************************************
+ * arch-x86/xen.h
+ * 
+ * Guest OS interface to x86 Xen.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004-2006, K A Fraser
+ */
+
+#include "../xen.h"
+
+#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
+#define __XEN_PUBLIC_ARCH_X86_XEN_H__
+
+/* Structural guest handles introduced in 0x00030201. */
+#if __XEN_INTERFACE_VERSION__ >= 0x00030201
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+    typedef struct { type *p; } __guest_handle_ ## name
+#else
+#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
+    typedef type * __guest_handle_ ## name
+#endif
+
+/*
+ * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
+ * in a struct in memory.
+ * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
+ * hypercall argument.
+ * XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but
+ * they might not be on other architectures.
+ */
+#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
+    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
+    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
+#define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
+#define __XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
+#define XEN_GUEST_HANDLE(name)          __XEN_GUEST_HANDLE(name)
+#define XEN_GUEST_HANDLE_PARAM(name)    XEN_GUEST_HANDLE(name)
+#define set_xen_guest_handle_raw(hnd, val)  do { (hnd).p = val; } while (0)
+#ifdef __XEN_TOOLS__
+#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
+#endif
+#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
+
+#if defined(__i386__)
+#include "xen-x86_32.h"
+#elif defined(__x86_64__)
+#include "xen-x86_64.h"
+#endif
+
+#ifndef __ASSEMBLY__
+typedef UINTN xen_pfn_t;
+#define PRI_xen_pfn "lx"
+#endif
+
+#define XEN_HAVE_PV_UPCALL_MASK 1
+
+/* Maximum number of virtual CPUs in legacy multi-processor guests. */
+#define XEN_LEGACY_MAX_VCPUS 32
+
+#ifndef __ASSEMBLY__
+
+typedef UINTN xen_ulong_t;
+#define PRI_xen_ulong "lx"
+
+typedef UINT64 tsc_timestamp_t; /* RDTSC timestamp */
+
+#ifdef __i386__
+#pragma pack(4)
+#endif
+struct arch_shared_info {
+    UINTN max_pfn;                  /* max pfn that appears in table */
+    /* Frame containing list of mfns containing list of mfns containing p2m. */
+    xen_pfn_t     pfn_to_mfn_frame_list_list;
+    UINTN nmi_reason;
+    UINT64 pad[32];
+};
+typedef struct arch_shared_info arch_shared_info_t;
+#ifdef __i386__
+#pragma pack()
+#endif
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/grant_table.h b/OvmfPkg/Include/IndustryStandard/Xen/grant_table.h
new file mode 100644
index 0000000..8725931
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/grant_table.h
@@ -0,0 +1,444 @@
+/******************************************************************************
+ * grant_table.h
+ *
+ * Interface for granting foreign access to page frames, and receiving
+ * page-ownership transfers.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
+#define __XEN_PUBLIC_GRANT_TABLE_H__
+
+#include "xen.h"
+
+/*
+ * `incontents 150 gnttab Grant Tables
+ *
+ * Xen's grant tables provide a generic mechanism to memory sharing
+ * between domains. This shared memory interface underpins the split
+ * device drivers for block and network IO.
+ *
+ * Each domain has its own grant table. This is a data structure that
+ * is shared with Xen; it allows the domain to tell Xen what kind of
+ * permissions other domains have on its pages. Entries in the grant
+ * table are identified by grant references. A grant reference is an
+ * integer, which indexes into the grant table. It acts as a
+ * capability which the grantee can use to perform operations on the
+ * granter’s memory.
+ *
+ * This capability-based system allows shared-memory communications
+ * between unprivileged domains. A grant reference also encapsulates
+ * the details of a shared page, removing the need for a domain to
+ * know the real machine address of a page it is sharing. This makes
+ * it possible to share memory correctly with domains running in
+ * fully virtualised memory.
+ */
+
+/***********************************
+ * GRANT TABLE REPRESENTATION
+ */
+
+/* Some rough guidelines on accessing and updating grant-table entries
+ * in a concurrency-safe manner. For more information, Linux contains a
+ * reference implementation for guest OSes (drivers/xen/grant_table.c, see
+ * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
+ *
+ * NB. WMB is a no-op on current-generation x86 processors. However, a
+ *     compiler barrier will still be required.
+ *
+ * Introducing a valid entry into the grant table:
+ *  1. Write ent->domid.
+ *  2. Write ent->frame:
+ *      GTF_permit_access:   Frame to which access is permitted.
+ *      GTF_accept_transfer: Pseudo-phys frame slot being filled by new
+ *                           frame, or zero if none.
+ *  3. Write memory barrier (WMB).
+ *  4. Write ent->flags, inc. valid type.
+ *
+ * Invalidating an unused GTF_permit_access entry:
+ *  1. flags = ent->flags.
+ *  2. Observe that !(flags & (GTF_reading|GTF_writing)).
+ *  3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
+ *  NB. No need for WMB as reuse of entry is control-dependent on success of
+ *      step 3, and all architectures guarantee ordering of ctrl-dep writes.
+ *
+ * Invalidating an in-use GTF_permit_access entry:
+ *  This cannot be done directly. Request assistance from the domain controller
+ *  which can set a timeout on the use of a grant entry and take necessary
+ *  action. (NB. This is not yet implemented!).
+ *
+ * Invalidating an unused GTF_accept_transfer entry:
+ *  1. flags = ent->flags.
+ *  2. Observe that !(flags & GTF_transfer_committed). [*]
+ *  3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
+ *  NB. No need for WMB as reuse of entry is control-dependent on success of
+ *      step 3, and all architectures guarantee ordering of ctrl-dep writes.
+ *  [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
+ *      The guest must /not/ modify the grant entry until the address of the
+ *      transferred frame is written. It is safe for the guest to spin waiting
+ *      for this to occur (detect by observing GTF_transfer_completed in
+ *      ent->flags).
+ *
+ * Invalidating a committed GTF_accept_transfer entry:
+ *  1. Wait for (ent->flags & GTF_transfer_completed).
+ *
+ * Changing a GTF_permit_access from writable to read-only:
+ *  Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
+ *
+ * Changing a GTF_permit_access from read-only to writable:
+ *  Use SMP-safe bit-setting instruction.
+ */
+
+/*
+ * Reference to a grant entry in a specified domain's grant table.
+ */
+typedef UINT32 grant_ref_t;
+
+/*
+ * A grant table comprises a packed array of grant entries in one or more
+ * page frames shared between Xen and a guest.
+ * [XEN]: This field is written by Xen and read by the sharing guest.
+ * [GST]: This field is written by the guest and read by Xen.
+ */
+
+/*
+ * Version 1 of the grant table entry structure is maintained purely
+ * for backwards compatibility.  New guests should use version 2.
+ */
+#if __XEN_INTERFACE_VERSION__ < 0x0003020a
+#define grant_entry_v1 grant_entry
+#define grant_entry_v1_t grant_entry_t
+#endif
+struct grant_entry_v1 {
+    /* GTF_xxx: various type and flag information.  [XEN,GST] */
+    UINT16 flags;
+    /* The domain being granted foreign privileges. [GST] */
+    domid_t  domid;
+    /*
+     * GTF_permit_access: Frame that @domid is allowed to map and access. [GST]
+     * GTF_accept_transfer: Frame whose ownership transferred by @domid. [XEN]
+     */
+    UINT32 frame;
+};
+typedef struct grant_entry_v1 grant_entry_v1_t;
+
+/* The first few grant table entries will be preserved across grant table
+ * version changes and may be pre-populated at domain creation by tools.
+ */
+#define GNTTAB_NR_RESERVED_ENTRIES     8
+#define GNTTAB_RESERVED_CONSOLE        0
+#define GNTTAB_RESERVED_XENSTORE       1
+
+/*
+ * Type of grant entry.
+ *  GTF_invalid: This grant entry grants no privileges.
+ *  GTF_permit_access: Allow @domid to map/access @frame.
+ *  GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
+ *                       to this guest. Xen writes the page number to @frame.
+ *  GTF_transitive: Allow @domid to transitively access a subrange of
+ *                  @trans_grant in @trans_domid.  No mappings are allowed.
+ */
+#define GTF_invalid         (0U<<0)
+#define GTF_permit_access   (1U<<0)
+#define GTF_accept_transfer (2U<<0)
+#define GTF_transitive      (3U<<0)
+#define GTF_type_mask       (3U<<0)
+
+/*
+ * Subflags for GTF_permit_access.
+ *  GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
+ *  GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
+ *  GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
+ *  GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
+ *  GTF_sub_page: Grant access to only a subrange of the page.  @domid
+ *                will only be allowed to copy from the grant, and not
+ *                map it. [GST]
+ */
+#define _GTF_readonly       (2)
+#define GTF_readonly        (1U<<_GTF_readonly)
+#define _GTF_reading        (3)
+#define GTF_reading         (1U<<_GTF_reading)
+#define _GTF_writing        (4)
+#define GTF_writing         (1U<<_GTF_writing)
+#define _GTF_PWT            (5)
+#define GTF_PWT             (1U<<_GTF_PWT)
+#define _GTF_PCD            (6)
+#define GTF_PCD             (1U<<_GTF_PCD)
+#define _GTF_PAT            (7)
+#define GTF_PAT             (1U<<_GTF_PAT)
+#define _GTF_sub_page       (8)
+#define GTF_sub_page        (1U<<_GTF_sub_page)
+
+/*
+ * Subflags for GTF_accept_transfer:
+ *  GTF_transfer_committed: Xen sets this flag to indicate that it is committed
+ *      to transferring ownership of a page frame. When a guest sees this flag
+ *      it must /not/ modify the grant entry until GTF_transfer_completed is
+ *      set by Xen.
+ *  GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
+ *      after reading GTF_transfer_committed. Xen will always write the frame
+ *      address, followed by ORing this flag, in a timely manner.
+ */
+#define _GTF_transfer_committed (2)
+#define GTF_transfer_committed  (1U<<_GTF_transfer_committed)
+#define _GTF_transfer_completed (3)
+#define GTF_transfer_completed  (1U<<_GTF_transfer_completed)
+
+/*
+ * Version 2 grant table entries.  These fulfil the same role as
+ * version 1 entries, but can represent more complicated operations.
+ * Any given domain will have either a version 1 or a version 2 table,
+ * and every entry in the table will be the same version.
+ *
+ * The interface by which domains use grant references does not depend
+ * on the grant table version in use by the other domain.
+ */
+#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
+/*
+ * Version 1 and version 2 grant entries share a common prefix.  The
+ * fields of the prefix are documented as part of struct
+ * grant_entry_v1.
+ */
+struct grant_entry_header {
+    UINT16 flags;
+    domid_t  domid;
+};
+typedef struct grant_entry_header grant_entry_header_t;
+
+/*
+ * Version 2 of the grant entry structure.
+ */
+union grant_entry_v2 {
+    grant_entry_header_t hdr;
+
+    /*
+     * This member is used for V1-style full page grants, where either:
+     *
+     * -- hdr.type is GTF_accept_transfer, or
+     * -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
+     *
+     * In that case, the frame field has the same semantics as the
+     * field of the same name in the V1 entry structure.
+     */
+    struct {
+        grant_entry_header_t hdr;
+        UINT32 pad0;
+        UINT64 frame;
+    } full_page;
+
+    /*
+     * If the grant type is GTF_grant_access and GTF_sub_page is set,
+     * @domid is allowed to access bytes [@page_off,@page_off+@length)
+     * in frame @frame.
+     */
+    struct {
+        grant_entry_header_t hdr;
+        UINT16 page_off;
+        UINT16 length;
+        UINT64 frame;
+    } sub_page;
+
+    /*
+     * If the grant is GTF_transitive, @domid is allowed to use the
+     * grant @gref in domain @trans_domid, as if it was the local
+     * domain.  Obviously, the transitive access must be compatible
+     * with the original grant.
+     *
+     * The current version of Xen does not allow transitive grants
+     * to be mapped.
+     */
+    struct {
+        grant_entry_header_t hdr;
+        domid_t trans_domid;
+        UINT16 pad0;
+        grant_ref_t gref;
+    } transitive;
+
+    UINT32 __spacer[4]; /* Pad to a power of two */
+};
+typedef union grant_entry_v2 grant_entry_v2_t;
+
+typedef UINT16 grant_status_t;
+
+#endif /* __XEN_INTERFACE_VERSION__ */
+
+/***********************************
+ * GRANT TABLE QUERIES AND USES
+ */
+
+/* ` enum neg_errnoval
+ * ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
+ * `                           VOID *args,
+ * `                           UINT32 count)
+ * `
+ *
+ * @args points to an array of a per-command data structure. The array
+ * has @count members
+ */
+
+/* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
+#define GNTTABOP_map_grant_ref        0
+#define GNTTABOP_unmap_grant_ref      1
+/* ` } */
+
+/*
+ * Handle to track a mapping created via a grant reference.
+ */
+typedef UINT32 grant_handle_t;
+
+/*
+ * GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
+ * by devices and/or host CPUs. If successful, <handle> is a tracking number
+ * that must be presented later to destroy the mapping(s). On error, <handle>
+ * is a negative status code.
+ * NOTES:
+ *  1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
+ *     via which I/O devices may access the granted frame.
+ *  2. If GNTMAP_host_map is specified then a mapping will be added at
+ *     either a host virtual address in the current address space, or at
+ *     a PTE at the specified machine address.  The type of mapping to
+ *     perform is selected through the GNTMAP_contains_pte flag, and the
+ *     address is specified in <host_addr>.
+ *  3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
+ *     host mapping is destroyed by other means then it is *NOT* guaranteed
+ *     to be accounted to the correct grant reference!
+ */
+struct gnttab_map_grant_ref {
+    /* IN parameters. */
+    UINT64 host_addr;
+    UINT32 flags;               /* GNTMAP_* */
+    grant_ref_t ref;
+    domid_t  dom;
+    /* OUT parameters. */
+    INT16  status;              /* => enum grant_status */
+    grant_handle_t handle;
+    UINT64 dev_bus_addr;
+};
+typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
+
+/*
+ * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
+ * tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
+ * field is ignored. If non-zero, they must refer to a device/host mapping
+ * that is tracked by <handle>
+ * NOTES:
+ *  1. The call may fail in an undefined manner if either mapping is not
+ *     tracked by <handle>.
+ *  3. After executing a batch of unmaps, it is guaranteed that no stale
+ *     mappings will remain in the device or host TLBs.
+ */
+struct gnttab_unmap_grant_ref {
+    /* IN parameters. */
+    UINT64 host_addr;
+    UINT64 dev_bus_addr;
+    grant_handle_t handle;
+    /* OUT parameters. */
+    INT16  status;              /* => enum grant_status */
+};
+typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
+DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
+
+/*
+ * Bitfield values for gnttab_map_grant_ref.flags.
+ */
+ /* Map the grant entry for access by I/O devices. */
+#define _GNTMAP_device_map      (0)
+#define GNTMAP_device_map       (1<<_GNTMAP_device_map)
+ /* Map the grant entry for access by host CPUs. */
+#define _GNTMAP_host_map        (1)
+#define GNTMAP_host_map         (1<<_GNTMAP_host_map)
+ /* Accesses to the granted frame will be restricted to read-only access. */
+#define _GNTMAP_readonly        (2)
+#define GNTMAP_readonly         (1<<_GNTMAP_readonly)
+ /*
+  * GNTMAP_host_map subflag:
+  *  0 => The host mapping is usable only by the guest OS.
+  *  1 => The host mapping is usable by guest OS + current application.
+  */
+#define _GNTMAP_application_map (3)
+#define GNTMAP_application_map  (1<<_GNTMAP_application_map)
+
+ /*
+  * GNTMAP_contains_pte subflag:
+  *  0 => This map request contains a host virtual address.
+  *  1 => This map request contains the machine addess of the PTE to update.
+  */
+#define _GNTMAP_contains_pte    (4)
+#define GNTMAP_contains_pte     (1<<_GNTMAP_contains_pte)
+
+#define _GNTMAP_can_fail        (5)
+#define GNTMAP_can_fail         (1<<_GNTMAP_can_fail)
+
+/*
+ * Bits to be placed in guest kernel available PTE bits (architecture
+ * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
+ */
+#define _GNTMAP_guest_avail0    (16)
+#define GNTMAP_guest_avail_mask ((UINT32)~0 << _GNTMAP_guest_avail0)
+
+/*
+ * Values for error status returns. All errors are -ve.
+ */
+/* ` enum grant_status { */
+#define GNTST_okay             (0)  /* Normal return.                        */
+#define GNTST_general_error    (-1) /* General undefined error.              */
+#define GNTST_bad_domain       (-2) /* Unrecognsed domain id.                */
+#define GNTST_bad_gntref       (-3) /* Unrecognised or inappropriate gntref. */
+#define GNTST_bad_handle       (-4) /* Unrecognised or inappropriate handle. */
+#define GNTST_bad_virt_addr    (-5) /* Inappropriate virtual address to map. */
+#define GNTST_bad_dev_addr     (-6) /* Inappropriate device address to unmap.*/
+#define GNTST_no_device_space  (-7) /* Out of space in I/O MMU.              */
+#define GNTST_permission_denied (-8) /* Not enough privilege for operation.  */
+#define GNTST_bad_page         (-9) /* Specified page was invalid for op.    */
+#define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary.   */
+#define GNTST_address_too_big (-11) /* transfer page address too large.      */
+#define GNTST_eagain          (-12) /* Operation not done; try again.        */
+/* ` } */
+
+#define GNTTABOP_error_msgs {                   \
+    "okay",                                     \
+    "undefined error",                          \
+    "unrecognised domain id",                   \
+    "invalid grant reference",                  \
+    "invalid mapping handle",                   \
+    "invalid virtual address",                  \
+    "invalid device address",                   \
+    "no spare translation slot in the I/O MMU", \
+    "permission denied",                        \
+    "bad page",                                 \
+    "copy arguments cross page boundary",       \
+    "page address size too large",              \
+    "operation not done; try again"             \
+}
+
+#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h b/OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h
new file mode 100644
index 0000000..120f62f
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h
@@ -0,0 +1,37 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
+#define __XEN_PUBLIC_HVM_HVM_OP_H__
+
+#include "../xen.h"
+
+/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
+#define HVMOP_set_param           0
+#define HVMOP_get_param           1
+struct xen_hvm_param {
+    domid_t  domid;    /* IN */
+    UINT32 index;    /* IN */
+    UINT64 value;    /* IN/OUT */
+};
+typedef struct xen_hvm_param xen_hvm_param_t;
+DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
+
+#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h b/OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h
new file mode 100644
index 0000000..517a184
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h
@@ -0,0 +1,150 @@
+/*
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
+#define __XEN_PUBLIC_HVM_PARAMS_H__
+
+#include "hvm_op.h"
+
+/*
+ * Parameter space for HVMOP_{set,get}_param.
+ */
+
+/*
+ * How should CPU0 event-channel notifications be delivered?
+ * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
+ * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
+ *                  Domain = val[47:32], Bus  = val[31:16],
+ *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
+ * val[63:56] == 2: val[7:0] is a vector number, check for
+ *                  XENFEAT_hvm_callback_vector to know if this delivery
+ *                  method is available.
+ * If val == 0 then CPU0 event-channel notifications are not delivered.
+ */
+#define HVM_PARAM_CALLBACK_IRQ 0
+
+/*
+ * These are not used by Xen. They are here for convenience of HVM-guest
+ * xenbus implementations.
+ */
+#define HVM_PARAM_STORE_PFN    1
+#define HVM_PARAM_STORE_EVTCHN 2
+
+#define HVM_PARAM_PAE_ENABLED  4
+
+#define HVM_PARAM_IOREQ_PFN    5
+
+#define HVM_PARAM_BUFIOREQ_PFN 6
+#define HVM_PARAM_BUFIOREQ_EVTCHN 26
+
+#if defined(__i386__) || defined(__x86_64__)
+
+/* Expose Viridian interfaces to this HVM guest? */
+#define HVM_PARAM_VIRIDIAN     9
+
+#endif
+
+/*
+ * Set mode for virtual timers (currently x86 only):
+ *  delay_for_missed_ticks (default):
+ *   Do not advance a vcpu's time beyond the correct delivery time for
+ *   interrupts that have been missed due to preemption. Deliver missed
+ *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
+ *   time stepwise for each one.
+ *  no_delay_for_missed_ticks:
+ *   As above, missed interrupts are delivered, but guest time always tracks
+ *   wallclock (i.e., real) time while doing so.
+ *  no_missed_ticks_pending:
+ *   No missed interrupts are held pending. Instead, to ensure ticks are
+ *   delivered at some non-zero rate, if we detect missed ticks then the
+ *   internal tick alarm is not disabled if the VCPU is preempted during the
+ *   next tick period.
+ *  one_missed_tick_pending:
+ *   Missed interrupts are collapsed together and delivered as one 'late tick'.
+ *   Guest time always tracks wallclock (i.e., real) time.
+ */
+#define HVM_PARAM_TIMER_MODE   10
+#define HVMPTM_delay_for_missed_ticks    0
+#define HVMPTM_no_delay_for_missed_ticks 1
+#define HVMPTM_no_missed_ticks_pending   2
+#define HVMPTM_one_missed_tick_pending   3
+
+/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
+#define HVM_PARAM_HPET_ENABLED 11
+
+/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
+#define HVM_PARAM_IDENT_PT     12
+
+/* Device Model domain, defaults to 0. */
+#define HVM_PARAM_DM_DOMAIN    13
+
+/* ACPI S state: currently support S0 and S3 on x86. */
+#define HVM_PARAM_ACPI_S_STATE 14
+
+/* TSS used on Intel when CR0.PE=0. */
+#define HVM_PARAM_VM86_TSS     15
+
+/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
+#define HVM_PARAM_VPT_ALIGN    16
+
+/* Console debug shared memory ring and event channel */
+#define HVM_PARAM_CONSOLE_PFN    17
+#define HVM_PARAM_CONSOLE_EVTCHN 18
+
+/*
+ * Select location of ACPI PM1a and TMR control blocks. Currently two locations
+ * are supported, specified by version 0 or 1 in this parameter:
+ *   - 0: default, use the old addresses
+ *        PM1A_EVT == 0x1f40; PM1A_CNT == 0x1f44; PM_TMR == 0x1f48
+ *   - 1: use the new default qemu addresses
+ *        PM1A_EVT == 0xb000; PM1A_CNT == 0xb004; PM_TMR == 0xb008
+ * You can find these address definitions in <hvm/ioreq.h>
+ */
+#define HVM_PARAM_ACPI_IOPORTS_LOCATION 19
+
+/* Enable blocking memory events, async or sync (pause vcpu until response) 
+ * onchangeonly indicates messages only on a change of value */
+#define HVM_PARAM_MEMORY_EVENT_CR0          20
+#define HVM_PARAM_MEMORY_EVENT_CR3          21
+#define HVM_PARAM_MEMORY_EVENT_CR4          22
+#define HVM_PARAM_MEMORY_EVENT_INT3         23
+#define HVM_PARAM_MEMORY_EVENT_SINGLE_STEP  25
+#define HVM_PARAM_MEMORY_EVENT_MSR          30
+
+#define HVMPME_MODE_MASK       (3 << 0)
+#define HVMPME_mode_disabled   0
+#define HVMPME_mode_async      1
+#define HVMPME_mode_sync       2
+#define HVMPME_onchangeonly    (1 << 2)
+
+/* Boolean: Enable nestedhvm (hvm only) */
+#define HVM_PARAM_NESTEDHVM    24
+
+/* Params for the mem event rings */
+#define HVM_PARAM_PAGING_RING_PFN   27
+#define HVM_PARAM_ACCESS_RING_PFN   28
+#define HVM_PARAM_SHARING_RING_PFN  29
+
+/* SHUTDOWN_* action in case of a triple fault */
+#define HVM_PARAM_TRIPLE_FAULT_REASON 31
+
+#define HVM_NR_PARAMS          32
+
+#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h b/OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h
new file mode 100644
index 0000000..80b196b
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * protocols.h
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef __XEN_PROTOCOLS_H__
+#define __XEN_PROTOCOLS_H__
+
+#define XEN_IO_PROTO_ABI_X86_32     "x86_32-abi"
+#define XEN_IO_PROTO_ABI_X86_64     "x86_64-abi"
+#define XEN_IO_PROTO_ABI_ARM        "arm-abi"
+
+#if defined(__i386__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
+#elif defined(__x86_64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
+#elif defined(__arm__) || defined(__aarch64__)
+# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
+#else
+# error arch fixup needed here
+#endif
+
+#endif
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/ring.h b/OvmfPkg/Include/IndustryStandard/Xen/io/ring.h
new file mode 100644
index 0000000..a8e9ea0
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/io/ring.h
@@ -0,0 +1,312 @@
+/******************************************************************************
+ * ring.h
+ * 
+ * Shared producer-consumer ring macros.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Tim Deegan and Andrew Warfield November 2004.
+ */
+
+#ifndef __XEN_PUBLIC_IO_RING_H__
+#define __XEN_PUBLIC_IO_RING_H__
+
+#include "../xen-compat.h"
+
+#if __XEN_INTERFACE_VERSION__ < 0x00030208
+#define xen_mb()  mb()
+#define xen_rmb() rmb()
+#define xen_wmb() wmb()
+#endif
+
+typedef UINT32 RING_IDX;
+
+/* Round a 32-bit unsigned constant down to the nearest power of two. */
+#define __RD2(_x)  (((_x) & 0x00000002) ? 0x2                  : ((_x) & 0x1))
+#define __RD4(_x)  (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2    : __RD2(_x))
+#define __RD8(_x)  (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4    : __RD4(_x))
+#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8    : __RD8(_x))
+#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
+
+/*
+ * Calculate size of a shared ring, given the total available space for the
+ * ring and indexes (_sz), and the name tag of the request/response structure.
+ * A ring contains as many entries as will fit, rounded down to the nearest 
+ * power of two (so we can mask with (size-1) to loop around).
+ */
+#define __CONST_RING_SIZE(_s, _sz) \
+    (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
+	    sizeof(((struct _s##_sring *)0)->ring[0])))
+/*
+ * The same for passing in an actual pointer instead of a name tag.
+ */
+#define __RING_SIZE(_s, _sz) \
+    (__RD32(((_sz) - (INTN)(_s)->ring + (INTN)(_s)) / sizeof((_s)->ring[0])))
+
+/*
+ * Macros to make the correct C datatypes for a new kind of ring.
+ * 
+ * To make a new ring datatype, you need to have two message structures,
+ * let's say request_t, and response_t already defined.
+ *
+ * In a header where you want the ring datatype declared, you then do:
+ *
+ *     DEFINE_RING_TYPES(mytag, request_t, response_t);
+ *
+ * These expand out to give you a set of types, as you can see below.
+ * The most important of these are:
+ * 
+ *     mytag_sring_t      - The shared ring.
+ *     mytag_front_ring_t - The 'front' half of the ring.
+ *     mytag_back_ring_t  - The 'back' half of the ring.
+ *
+ * To initialize a ring in your code you need to know the location and size
+ * of the shared memory area (PAGE_SIZE, for instance). To initialise
+ * the front half:
+ *
+ *     mytag_front_ring_t front_ring;
+ *     SHARED_RING_INIT((mytag_sring_t *)shared_page);
+ *     FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ *
+ * Initializing the back follows similarly (note that only the front
+ * initializes the shared ring):
+ *
+ *     mytag_back_ring_t back_ring;
+ *     BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
+ */
+
+#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \
+                                                                        \
+/* Shared ring entry */                                                 \
+union __name##_sring_entry {                                            \
+    __req_t req;                                                        \
+    __rsp_t rsp;                                                        \
+};                                                                      \
+                                                                        \
+/* Shared ring page */                                                  \
+struct __name##_sring {                                                 \
+    RING_IDX req_prod, req_event;                                       \
+    RING_IDX rsp_prod, rsp_event;                                       \
+    union {                                                             \
+        struct {                                                        \
+            UINT8 smartpoll_active;                                   \
+        } netif;                                                        \
+        struct {                                                        \
+            UINT8 msg;                                                \
+        } tapif_user;                                                   \
+        UINT8 pvt_pad[4];                                             \
+    } private;                                                          \
+    UINT8 __pad[44];                                                  \
+    union __name##_sring_entry ring[1]; /* variable-length */           \
+};                                                                      \
+                                                                        \
+/* "Front" end's private variables */                                   \
+struct __name##_front_ring {                                            \
+    RING_IDX req_prod_pvt;                                              \
+    RING_IDX rsp_cons;                                                  \
+    UINT32 nr_ents;                                               \
+    struct __name##_sring *sring;                                       \
+};                                                                      \
+                                                                        \
+/* "Back" end's private variables */                                    \
+struct __name##_back_ring {                                             \
+    RING_IDX rsp_prod_pvt;                                              \
+    RING_IDX req_cons;                                                  \
+    UINT32 nr_ents;                                               \
+    struct __name##_sring *sring;                                       \
+};                                                                      \
+                                                                        \
+/* Syntactic sugar */                                                   \
+typedef struct __name##_sring __name##_sring_t;                         \
+typedef struct __name##_front_ring __name##_front_ring_t;               \
+typedef struct __name##_back_ring __name##_back_ring_t
+
+/*
+ * Macros for manipulating rings.
+ * 
+ * FRONT_RING_whatever works on the "front end" of a ring: here 
+ * requests are pushed on to the ring and responses taken off it.
+ * 
+ * BACK_RING_whatever works on the "back end" of a ring: here 
+ * requests are taken off the ring and responses put on.
+ * 
+ * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL. 
+ * This is OK in 1-for-1 request-response situations where the 
+ * requestor (front end) never has more than RING_SIZE()-1
+ * outstanding requests.
+ */
+
+/* Initialising empty rings */
+#define SHARED_RING_INIT(_s) do {                                       \
+    (_s)->req_prod  = (_s)->rsp_prod  = 0;                              \
+    (_s)->req_event = (_s)->rsp_event = 1;                              \
+    (VOID)ZeroMem((_s)->private.pvt_pad, sizeof((_s)->private.pvt_pad)); \
+    (VOID)ZeroMem((_s)->__pad, sizeof((_s)->__pad));                  \
+} while(0)
+
+#define FRONT_RING_INIT(_r, _s, __size) do {                            \
+    (_r)->req_prod_pvt = 0;                                             \
+    (_r)->rsp_cons = 0;                                                 \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+    (_r)->sring = (_s);                                                 \
+} while (0)
+
+#define BACK_RING_INIT(_r, _s, __size) do {                             \
+    (_r)->rsp_prod_pvt = 0;                                             \
+    (_r)->req_cons = 0;                                                 \
+    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
+    (_r)->sring = (_s);                                                 \
+} while (0)
+
+/* How big is this ring? */
+#define RING_SIZE(_r)                                                   \
+    ((_r)->nr_ents)
+
+/* Number of free requests (for use on front side only). */
+#define RING_FREE_REQUESTS(_r)                                          \
+    (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
+
+/* Test if there is an empty slot available on the front ring.
+ * (This is only meaningful from the front. )
+ */
+#define RING_FULL(_r)                                                   \
+    (RING_FREE_REQUESTS(_r) == 0)
+
+/* Test if there are outstanding messages to be processed on a ring. */
+#define RING_HAS_UNCONSUMED_RESPONSES(_r)                               \
+    ((_r)->sring->rsp_prod - (_r)->rsp_cons)
+
+#ifdef __GNUC__
+#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({                             \
+    UINT32 req = (_r)->sring->req_prod - (_r)->req_cons;          \
+    UINT32 rsp = RING_SIZE(_r) -                                  \
+        ((_r)->req_cons - (_r)->rsp_prod_pvt);                          \
+    req < rsp ? req : rsp;                                              \
+})
+#else
+/* Same as above, but without the nice GCC ({ ... }) syntax. */
+#define RING_HAS_UNCONSUMED_REQUESTS(_r)                                \
+    ((((_r)->sring->req_prod - (_r)->req_cons) <                        \
+      (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ?        \
+     ((_r)->sring->req_prod - (_r)->req_cons) :                         \
+     (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
+#endif
+
+/* Direct access to individual ring elements, by index. */
+#define RING_GET_REQUEST(_r, _idx)                                      \
+    (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+
+#define RING_GET_RESPONSE(_r, _idx)                                     \
+    (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
+
+/* Loop termination condition: Would the specified index overflow the ring? */
+#define RING_REQUEST_CONS_OVERFLOW(_r, _cons)                           \
+    (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
+
+/* Ill-behaved frontend determination: Can there be this many requests? */
+#define RING_REQUEST_PROD_OVERFLOW(_r, _prod)                           \
+    (((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
+
+#define RING_PUSH_REQUESTS(_r) do {                                     \
+    xen_wmb(); /* back sees requests /before/ updated producer index */ \
+    (_r)->sring->req_prod = (_r)->req_prod_pvt;                         \
+} while (0)
+
+#define RING_PUSH_RESPONSES(_r) do {                                    \
+    xen_wmb(); /* front sees resps /before/ updated producer index */   \
+    (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt;                         \
+} while (0)
+
+/*
+ * Notification hold-off (req_event and rsp_event):
+ * 
+ * When queueing requests or responses on a shared ring, it may not always be
+ * necessary to notify the remote end. For example, if requests are in flight
+ * in a backend, the front may be able to queue further requests without
+ * notifying the back (if the back checks for new requests when it queues
+ * responses).
+ * 
+ * When enqueuing requests or responses:
+ * 
+ *  Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
+ *  is a boolean return value. True indicates that the receiver requires an
+ *  asynchronous notification.
+ * 
+ * After dequeuing requests or responses (before sleeping the connection):
+ * 
+ *  Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
+ *  The second argument is a boolean return value. True indicates that there
+ *  are pending messages on the ring (i.e., the connection should not be put
+ *  to sleep).
+ * 
+ *  These macros will set the req_event/rsp_event field to trigger a
+ *  notification on the very next message that is enqueued. If you want to
+ *  create batches of work (i.e., only receive a notification after several
+ *  messages have been enqueued) then you will need to create a customised
+ *  version of the FINAL_CHECK macro in your own code, which sets the event
+ *  field appropriately.
+ */
+
+#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do {           \
+    RING_IDX __old = (_r)->sring->req_prod;                             \
+    RING_IDX __new = (_r)->req_prod_pvt;                                \
+    xen_wmb(); /* back sees requests /before/ updated producer index */ \
+    (_r)->sring->req_prod = __new;                                      \
+    xen_mb(); /* back sees new requests /before/ we check req_event */  \
+    (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) <           \
+                 (RING_IDX)(__new - __old));                            \
+} while (0)
+
+#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do {          \
+    RING_IDX __old = (_r)->sring->rsp_prod;                             \
+    RING_IDX __new = (_r)->rsp_prod_pvt;                                \
+    xen_wmb(); /* front sees resps /before/ updated producer index */   \
+    (_r)->sring->rsp_prod = __new;                                      \
+    xen_mb(); /* front sees new resps /before/ we check rsp_event */    \
+    (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) <           \
+                 (RING_IDX)(__new - __old));                            \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do {             \
+    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
+    if (_work_to_do) break;                                             \
+    (_r)->sring->req_event = (_r)->req_cons + 1;                        \
+    xen_mb();                                                           \
+    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
+} while (0)
+
+#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do {            \
+    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
+    if (_work_to_do) break;                                             \
+    (_r)->sring->rsp_event = (_r)->rsp_cons + 1;                        \
+    xen_mb();                                                           \
+    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
+} while (0)
+
+#endif /* __XEN_PUBLIC_IO_RING_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h b/OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h
new file mode 100644
index 0000000..927f9db
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * xenbus.h
+ *
+ * Xenbus protocol details.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 XenSource Ltd.
+ */
+
+#ifndef _XEN_PUBLIC_IO_XENBUS_H
+#define _XEN_PUBLIC_IO_XENBUS_H
+
+/*
+ * The state of either end of the Xenbus, i.e. the current communication
+ * status of initialisation across the bus.  States here imply nothing about
+ * the state of the connection between the driver and the kernel's device
+ * layers.
+ */
+enum xenbus_state {
+    XenbusStateUnknown       = 0,
+
+    XenbusStateInitialising  = 1,
+
+    /*
+     * InitWait: Finished early initialisation but waiting for information
+     * from the peer or hotplug scripts.
+     */
+    XenbusStateInitWait      = 2,
+
+    /*
+     * Initialised: Waiting for a connection from the peer.
+     */
+    XenbusStateInitialised   = 3,
+
+    XenbusStateConnected     = 4,
+
+    /*
+     * Closing: The device is being closed due to an error or an unplug event.
+     */
+    XenbusStateClosing       = 5,
+
+    XenbusStateClosed        = 6,
+
+    /*
+     * Reconfiguring: The device is being reconfigured.
+     */
+    XenbusStateReconfiguring = 7,
+
+    XenbusStateReconfigured  = 8
+};
+typedef enum xenbus_state XenbusState;
+
+#endif /* _XEN_PUBLIC_IO_XENBUS_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/memory.h b/OvmfPkg/Include/IndustryStandard/Xen/memory.h
new file mode 100644
index 0000000..00156a4
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/memory.h
@@ -0,0 +1,94 @@
+/******************************************************************************
+ * memory.h
+ * 
+ * Memory reservation and information.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
+ */
+
+#ifndef __XEN_PUBLIC_MEMORY_H__
+#define __XEN_PUBLIC_MEMORY_H__
+
+#include "xen.h"
+
+/* Source mapping space. */
+/* ` enum phys_map_space { */
+#define XENMAPSPACE_shared_info  0 /* shared info page */
+#define XENMAPSPACE_grant_table  1 /* grant table page */
+#define XENMAPSPACE_gmfn         2 /* GMFN */
+#define XENMAPSPACE_gmfn_range   3 /* GMFN range, XENMEM_add_to_physmap only. */
+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
+                                    * XENMEM_add_to_physmap_batch only. */
+/* ` } */
+
+/*
+ * Sets the GPFN at which a particular page appears in the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_add_to_physmap_t.
+ */
+#define XENMEM_add_to_physmap      7
+struct xen_add_to_physmap {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+
+    /* Number of pages to go through for gmfn_range */
+    UINT16    size;
+
+    UINT32 space; /* => enum phys_map_space */
+
+#define XENMAPIDX_grant_table_status 0x80000000
+
+    /* Index into space being mapped. */
+    xen_ulong_t idx;
+
+    /* GPFN in domid where the source mapping page should appear. */
+    xen_pfn_t     gpfn;
+};
+typedef struct xen_add_to_physmap xen_add_to_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
+
+/*
+ * Unmaps the page appearing at a particular GPFN from the specified guest's
+ * pseudophysical address space.
+ * arg == addr of xen_remove_from_physmap_t.
+ */
+#define XENMEM_remove_from_physmap      15
+struct xen_remove_from_physmap {
+    /* Which domain to change the mapping for. */
+    domid_t domid;
+
+    /* GPFN of the current mapping of the page. */
+    xen_pfn_t     gpfn;
+};
+typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
+DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
+
+#endif /* __XEN_PUBLIC_MEMORY_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h b/OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h
new file mode 100644
index 0000000..3eb80a0
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ * xen-compat.h
+ * 
+ * Guest OS interface to Xen.  Compatibility layer.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2006, Christian Limpach
+ */
+
+#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
+#define __XEN_PUBLIC_XEN_COMPAT_H__
+
+#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040400
+
+#if defined(__XEN__) || defined(__XEN_TOOLS__)
+/* Xen is built with matching headers and implements the latest interface. */
+#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
+#elif !defined(__XEN_INTERFACE_VERSION__)
+/* Guests which do not specify a version get the legacy interface. */
+#define __XEN_INTERFACE_VERSION__ 0x00000000
+#endif
+
+#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
+#error "These header files do not support the requested interface version."
+#endif
+
+#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
diff --git a/OvmfPkg/Include/IndustryStandard/Xen/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
new file mode 100644
index 0000000..b93bd47
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
@@ -0,0 +1,341 @@
+/******************************************************************************
+ * xen.h
+ * 
+ * Guest OS interface to Xen.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2004, K A Fraser
+ */
+
+#ifndef __XEN_PUBLIC_XEN_H__
+#define __XEN_PUBLIC_XEN_H__
+
+#include "xen-compat.h"
+
+#if defined(__i386__) || defined(__x86_64__)
+#include "arch-x86/xen.h"
+#elif defined(__arm__) || defined (__aarch64__)
+#include "arch-arm.h"
+#else
+#error "Unsupported architecture"
+#endif
+
+#ifndef __ASSEMBLY__
+/* Guest handles for primitive C types. */
+DEFINE_XEN_GUEST_HANDLE(CHAR8);
+/* __DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); */
+DEFINE_XEN_GUEST_HANDLE(INT32);
+__DEFINE_XEN_GUEST_HANDLE(uint,  UINT32);
+#if __XEN_INTERFACE_VERSION__ < 0x00040300
+DEFINE_XEN_GUEST_HANDLE(INTN);
+__DEFINE_XEN_GUEST_HANDLE(ulong, UINTN);
+#endif
+DEFINE_XEN_GUEST_HANDLE(VOID);
+
+DEFINE_XEN_GUEST_HANDLE(UINT64);
+DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
+DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
+#endif
+
+/*
+ * HYPERCALLS
+ */
+
+/* `incontents 100 hcalls List of hypercalls
+ * ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*()
+ */
+
+#define __HYPERVISOR_set_trap_table        0
+#define __HYPERVISOR_mmu_update            1
+#define __HYPERVISOR_set_gdt               2
+#define __HYPERVISOR_stack_switch          3
+#define __HYPERVISOR_set_callbacks         4
+#define __HYPERVISOR_fpu_taskswitch        5
+#define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
+#define __HYPERVISOR_platform_op           7
+#define __HYPERVISOR_set_debugreg          8
+#define __HYPERVISOR_get_debugreg          9
+#define __HYPERVISOR_update_descriptor    10
+#define __HYPERVISOR_memory_op            12
+#define __HYPERVISOR_multicall            13
+#define __HYPERVISOR_update_va_mapping    14
+#define __HYPERVISOR_set_timer_op         15
+#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
+#define __HYPERVISOR_xen_version          17
+#define __HYPERVISOR_console_io           18
+#define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
+#define __HYPERVISOR_grant_table_op       20
+#define __HYPERVISOR_vm_assist            21
+#define __HYPERVISOR_update_va_mapping_otherdomain 22
+#define __HYPERVISOR_iret                 23 /* x86 only */
+#define __HYPERVISOR_vcpu_op              24
+#define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
+#define __HYPERVISOR_mmuext_op            26
+#define __HYPERVISOR_xsm_op               27
+#define __HYPERVISOR_nmi_op               28
+#define __HYPERVISOR_sched_op             29
+#define __HYPERVISOR_callback_op          30
+#define __HYPERVISOR_xenoprof_op          31
+#define __HYPERVISOR_event_channel_op     32
+#define __HYPERVISOR_physdev_op           33
+#define __HYPERVISOR_hvm_op               34
+#define __HYPERVISOR_sysctl               35
+#define __HYPERVISOR_domctl               36
+#define __HYPERVISOR_kexec_op             37
+#define __HYPERVISOR_tmem_op              38
+#define __HYPERVISOR_xc_reserved_op       39 /* reserved for XenClient */
+
+/* Architecture-specific hypercall definitions. */
+#define __HYPERVISOR_arch_0               48
+#define __HYPERVISOR_arch_1               49
+#define __HYPERVISOR_arch_2               50
+#define __HYPERVISOR_arch_3               51
+#define __HYPERVISOR_arch_4               52
+#define __HYPERVISOR_arch_5               53
+#define __HYPERVISOR_arch_6               54
+#define __HYPERVISOR_arch_7               55
+
+/* ` } */
+
+/*
+ * HYPERCALL COMPATIBILITY.
+ */
+
+/* New sched_op hypercall introduced in 0x00030101. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030101
+#undef __HYPERVISOR_sched_op
+#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
+#endif
+
+/* New event-channel and physdev hypercalls introduced in 0x00030202. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030202
+#undef __HYPERVISOR_event_channel_op
+#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
+#undef __HYPERVISOR_physdev_op
+#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
+#endif
+
+/* New platform_op hypercall introduced in 0x00030204. */
+#if __XEN_INTERFACE_VERSION__ < 0x00030204
+#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
+#endif
+
+#ifndef __ASSEMBLY__
+
+typedef UINT16 domid_t;
+
+/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
+#define DOMID_FIRST_RESERVED (0x7FF0U)
+
+/* DOMID_SELF is used in certain contexts to refer to oneself. */
+#define DOMID_SELF (0x7FF0U)
+
+/*
+ * DOMID_IO is used to restrict page-table updates to mapping I/O memory.
+ * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
+ * is useful to ensure that no mappings to the OS's own heap are accidentally
+ * installed. (e.g., in Linux this could cause havoc as reference counts
+ * aren't adjusted on the I/O-mapping code path).
+ * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can
+ * be specified by any calling domain.
+ */
+#define DOMID_IO   (0x7FF1U)
+
+/*
+ * DOMID_XEN is used to allow privileged domains to map restricted parts of
+ * Xen's heap space (e.g., the machine_to_phys table).
+ * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if
+ * the caller is privileged.
+ */
+#define DOMID_XEN  (0x7FF2U)
+
+/*
+ * DOMID_COW is used as the owner of sharable pages */
+#define DOMID_COW  (0x7FF3U)
+
+/* DOMID_INVALID is used to identify pages with unknown owner. */
+#define DOMID_INVALID (0x7FF4U)
+
+/* Idle domain. */
+#define DOMID_IDLE (0x7FFFU)
+
+#if __XEN_INTERFACE_VERSION__ < 0x00040400
+/*
+ * Event channel endpoints per domain (when using the 2-level ABI):
+ *  1024 if a INTN is 32 bits; 4096 if a INTN is 64 bits.
+ */
+#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
+#endif
+
+struct vcpu_time_info {
+    /*
+     * Updates to the following values are preceded and followed by an
+     * increment of 'version'. The guest can therefore detect updates by
+     * looking for changes to 'version'. If the least-significant bit of
+     * the version number is set then an update is in progress and the guest
+     * must wait to read a consistent set of values.
+     * The correct way to interact with the version number is similar to
+     * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
+     */
+    UINT32 version;
+    UINT32 pad0;
+    UINT64 tsc_timestamp;   /* TSC at last update of time vals.  */
+    UINT64 system_time;     /* Time, in nanosecs, since boot.    */
+    /*
+     * Current system time:
+     *   system_time +
+     *   ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
+     * CPU frequency (Hz):
+     *   ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
+     */
+    UINT32 tsc_to_system_mul;
+    INT8   tsc_shift;
+    INT8   pad1[3];
+}; /* 32 bytes */
+typedef struct vcpu_time_info vcpu_time_info_t;
+
+struct vcpu_info {
+    /*
+     * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
+     * a pending notification for a particular VCPU. It is then cleared 
+     * by the guest OS /before/ checking for pending work, thus avoiding
+     * a set-and-check race. Note that the mask is only accessed by Xen
+     * on the CPU that is currently hosting the VCPU. This means that the
+     * pending and mask flags can be updated by the guest without special
+     * synchronisation (i.e., no need for the x86 LOCK prefix).
+     * This may seem suboptimal because if the pending flag is set by
+     * a different CPU then an IPI may be scheduled even when the mask
+     * is set. However, note:
+     *  1. The task of 'interrupt holdoff' is covered by the per-event-
+     *     channel mask bits. A 'noisy' event that is continually being
+     *     triggered can be masked at source at this very precise
+     *     granularity.
+     *  2. The main purpose of the per-VCPU mask is therefore to restrict
+     *     reentrant execution: whether for concurrency control, or to
+     *     prevent unbounded stack usage. Whatever the purpose, we expect
+     *     that the mask will be asserted only for short periods at a time,
+     *     and so the likelihood of a 'spurious' IPI is suitably small.
+     * The mask is read before making an event upcall to the guest: a
+     * non-zero mask therefore guarantees that the VCPU will not receive
+     * an upcall activation. The mask is cleared when the VCPU requests
+     * to block: this avoids wakeup-waiting races.
+     */
+    UINT8 evtchn_upcall_pending;
+#ifdef XEN_HAVE_PV_UPCALL_MASK
+    UINT8 evtchn_upcall_mask;
+#else /* XEN_HAVE_PV_UPCALL_MASK */
+    UINT8 pad0;
+#endif /* XEN_HAVE_PV_UPCALL_MASK */
+    xen_ulong_t evtchn_pending_sel;
+    struct arch_vcpu_info arch;
+    struct vcpu_time_info time;
+}; /* 64 bytes (x86) */
+#ifndef __XEN__
+typedef struct vcpu_info vcpu_info_t;
+#endif
+
+/*
+ * `incontents 200 startofday_shared Start-of-day shared data structure
+ * Xen/kernel shared data -- pointer provided in start_info.
+ *
+ * This structure is defined to be both smaller than a page, and the
+ * only data on the shared page, but may vary in actual size even within
+ * compatible Xen versions; guests should not rely on the size
+ * of this structure remaining constant.
+ */
+struct shared_info {
+    struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
+
+    /*
+     * A domain can create "event channels" on which it can send and receive
+     * asynchronous event notifications. There are three classes of event that
+     * are delivered by this mechanism:
+     *  1. Bi-directional inter- and intra-domain connections. Domains must
+     *     arrange out-of-band to set up a connection (usually by allocating
+     *     an unbound 'listener' port and avertising that via a storage service
+     *     such as xenstore).
+     *  2. Physical interrupts. A domain with suitable hardware-access
+     *     privileges can bind an event-channel port to a physical interrupt
+     *     source.
+     *  3. Virtual interrupts ('events'). A domain can bind an event-channel
+     *     port to a virtual interrupt source, such as the virtual-timer
+     *     device or the emergency console.
+     * 
+     * Event channels are addressed by a "port index". Each channel is
+     * associated with two bits of information:
+     *  1. PENDING -- notifies the domain that there is a pending notification
+     *     to be processed. This bit is cleared by the guest.
+     *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
+     *     will cause an asynchronous upcall to be scheduled. This bit is only
+     *     updated by the guest. It is read-only within Xen. If a channel
+     *     becomes pending while the channel is masked then the 'edge' is lost
+     *     (i.e., when the channel is unmasked, the guest must manually handle
+     *     pending notifications as no upcall will be scheduled by Xen).
+     * 
+     * To expedite scanning of pending notifications, any 0->1 pending
+     * transition on an unmasked channel causes a corresponding bit in a
+     * per-vcpu selector word to be set. Each bit in the selector covers a
+     * 'C INTN' in the PENDING bitfield array.
+     */
+    xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
+    xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
+
+    /*
+     * Wallclock time: updated only by control software. Guests should base
+     * their gettimeofday() syscall on this wallclock-base value.
+     */
+    UINT32 wc_version;      /* Version counter: see vcpu_time_info_t. */
+    UINT32 wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
+    UINT32 wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
+
+    struct arch_shared_info arch;
+
+};
+#ifndef __XEN__
+typedef struct shared_info shared_info_t;
+#endif
+
+/* Turn a plain number into a C UINTN constant. */
+#define __mk_unsigned_long(x) x ## UL
+#define mk_unsigned_long(x) __mk_unsigned_long(x)
+
+__DEFINE_XEN_GUEST_HANDLE(uint8,  UINT8);
+__DEFINE_XEN_GUEST_HANDLE(uint16, UINT16);
+__DEFINE_XEN_GUEST_HANDLE(uint32, UINT32);
+__DEFINE_XEN_GUEST_HANDLE(uint64, UINT64);
+
+#else /* __ASSEMBLY__ */
+
+/* In assembly code we cannot use C numeric constant suffixes. */
+#define mk_unsigned_long(x) x
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __XEN_PUBLIC_XEN_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
Anthony PERARD


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

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

* [PATCH v3 03/19] OvmfPkg: Add basic skeleton for the XenBus bus driver.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
  2014-10-17 17:03 ` [PATCH v3 01/19] OvmfPkg: Add the MIT license to License.txt Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 04/19] OvmfPkg/XenBusDxe: Add device state struct and create an ExitBoot services event Anthony PERARD
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This includes Component Name and Driver Binding.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Change in V3:
- enable compilation for Ia32 and Ia32X64
- fix version (driver binding)

Change in V2:
- Simple support of controller name.
- Cleaning up comments, files header.
- Add Licenses
- Rename XenbusDxe to XenBusDxe.
---
 OvmfPkg/OvmfPkgIa32.dsc           |   1 +
 OvmfPkg/OvmfPkgIa32.fdf           |   1 +
 OvmfPkg/OvmfPkgIa32X64.dsc        |   1 +
 OvmfPkg/OvmfPkgIa32X64.fdf        |   1 +
 OvmfPkg/OvmfPkgX64.dsc            |   1 +
 OvmfPkg/OvmfPkgX64.fdf            |   1 +
 OvmfPkg/XenBusDxe/ComponentName.c | 190 +++++++++++++++++++++++
 OvmfPkg/XenBusDxe/ComponentName.h | 110 +++++++++++++
 OvmfPkg/XenBusDxe/DriverBinding.h | 144 +++++++++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.c     | 317 ++++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.h     |  93 +++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.inf   |  56 +++++++
 12 files changed, 916 insertions(+)
 create mode 100644 OvmfPkg/XenBusDxe/ComponentName.c
 create mode 100644 OvmfPkg/XenBusDxe/ComponentName.h
 create mode 100644 OvmfPkg/XenBusDxe/DriverBinding.h
 create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.c
 create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.h
 create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.inf

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 8527ece..c16aea2 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -428,6 +428,7 @@
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+  OvmfPkg/XenBusDxe/XenBusDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
     <LibraryClasses>
       PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index ef3cdef..0b75fd2 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -227,6 +227,7 @@ INF  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
 INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 823f005..340ef00 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -435,6 +435,7 @@
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+  OvmfPkg/XenBusDxe/XenBusDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
     <LibraryClasses>
       PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 375afac..146e57f 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -227,6 +227,7 @@ INF  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
 INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 40c18de..74c799c 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -433,6 +433,7 @@
   OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+  OvmfPkg/XenBusDxe/XenBusDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
     <LibraryClasses>
       PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index a0c1ac1..8b6a80b 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -227,6 +227,7 @@ INF  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
 INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
diff --git a/OvmfPkg/XenBusDxe/ComponentName.c b/OvmfPkg/XenBusDxe/ComponentName.c
new file mode 100644
index 0000000..bcf1e51
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/ComponentName.c
@@ -0,0 +1,190 @@
+/** @file
+  Component Name functions implementation for XenBus Bus driver.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "XenBusDxe.h"
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL  gXenBusDxeComponentName = {
+  (EFI_COMPONENT_NAME_GET_DRIVER_NAME)    XenBusDxeComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)XenBusDxeComponentNameGetControllerName,
+  "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL  gXenBusDxeComponentName2 = {
+  XenBusDxeComponentNameGetDriverName,
+  XenBusDxeComponentNameGetControllerName,
+  "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mXenBusDxeDriverNameTable[] = {
+  { "eng;en", (CHAR16 *)L"XenBus Bus Driver" },
+  { NULL, NULL }
+};
+
+///
+/// Table of controller names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mXenBusDxeControllerNameTable[] = {
+  { "eng;en", (CHAR16 *)L"XenBus Controller" },
+  { NULL, NULL }
+};
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that that the caller
+                     is requesting, and it must match one of the languages specified
+                     in SupportedLanguages.  The number of languages supported by a
+                     driver is up to the driver writer.
+  @param  DriverName A pointer to the Unicode string to return.  This Unicode string
+                     is the name of the driver specified by This in the language
+                     specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This
+                                and the language specified by Language was returned
+                                in DriverName.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mXenBusDxeDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This != &gXenBusDxeComponentName2)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle The handle of a controller that the driver specified by
+                           This is managing.  This handle specifies the controller
+                           whose name is to be returned.
+  @param  ChildHandle      The handle of the child controller to retrieve the name
+                           of.  This is an optional parameter that may be NULL.  It
+                           will be NULL for device drivers.  It will also be NULL
+                           for a bus drivers that wish to retrieve the name of the
+                           bus controller.  It will not be NULL for a bus driver
+                           that wishes to retrieve the name of a child controller.
+  @param  Language         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller name
+                           that the caller is requesting, and it must match one
+                           of the languages specified in SupportedLanguages.  The
+                           number of languages supported by a driver is up to the
+                           driver writer.
+  @param  ControllerName   A pointer to the Unicode string to return.  This Unicode
+                           string is the name of the controller specified by
+                           ControllerHandle and ChildHandle in the language specified
+                           by Language, from the point of view of the driver specified
+                           by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user-readable name in the
+                                language specified by Language for the driver
+                                specified by This was returned in DriverName.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently managing
+                                the controller specified by ControllerHandle and
+                                ChildHandle.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  )
+{
+  EFI_STATUS  Status;
+
+  if (ChildHandle != NULL) {
+    // TODO Get controller name for a child.
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Make sure this driver is currently managing ControllerHandle
+  //
+  Status = EfiTestManagedDevice (
+             ControllerHandle,
+             gXenBusDxeDriverBinding.DriverBindingHandle,
+             &gEfiPciIoProtocolGuid
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Lookup name of controller specified by ControllerHandle
+  //
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mXenBusDxeControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This != &gXenBusDxeComponentName2)
+           );
+}
diff --git a/OvmfPkg/XenBusDxe/ComponentName.h b/OvmfPkg/XenBusDxe/ComponentName.h
new file mode 100644
index 0000000..dfafce6
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/ComponentName.h
@@ -0,0 +1,110 @@
+/** @file
+  Component Name functions declaration for XenBus Bus driver.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that that the caller
+                     is requesting, and it must match one of the languages specified
+                     in SupportedLanguages.  The number of languages supported by a
+                     driver is up to the driver writer.
+  @param  DriverName A pointer to the Unicode string to return.  This Unicode string
+                     is the name of the driver specified by This in the language
+                     specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This
+                                and the language specified by Language was returned
+                                in DriverName.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle The handle of a controller that the driver specified by
+                           This is managing.  This handle specifies the controller
+                           whose name is to be returned.
+  @param  ChildHandle      The handle of the child controller to retrieve the name
+                           of.  This is an optional parameter that may be NULL.  It
+                           will be NULL for device drivers.  It will also be NULL
+                           for a bus drivers that wish to retrieve the name of the
+                           bus controller.  It will not be NULL for a bus driver
+                           that wishes to retrieve the name of a child controller.
+  @param  Language         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller name
+                           that the caller is requesting, and it must match one
+                           of the languages specified in SupportedLanguages.  The
+                           number of languages supported by a driver is up to the
+                           driver writer.
+  @param  ControllerName   A pointer to the Unicode string to return.  This Unicode
+                           string is the name of the controller specified by
+                           ControllerHandle and ChildHandle in the language specified
+                           by Language, from the point of view of the driver specified
+                           by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user-readable name in the
+                                language specified by Language for the driver
+                                specified by This was returned in DriverName.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently managing
+                                the controller specified by ControllerHandle and
+                                ChildHandle.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  );
diff --git a/OvmfPkg/XenBusDxe/DriverBinding.h b/OvmfPkg/XenBusDxe/DriverBinding.h
new file mode 100644
index 0000000..13e0a90
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/DriverBinding.h
@@ -0,0 +1,144 @@
+/** @file
+  Driver Binding functions declaration for XenBus Bus driver.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+/**
+  Tests to see if this driver supports a given controller. If a child device is provided,
+  it further tests to see if this driver supports creating a handle for the specified child device.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For bus drivers, if this parameter is not NULL, then
+                                   the bus driver must determine if the bus controller specified
+                                   by ControllerHandle and the child controller specified
+                                   by RemainingDevicePath are both supported by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by a different
+                                   driver or an application that requires exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service ConnectController().
+  As a result, much of the error checking on the parameters to Start() has been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver specified by This must
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For a bus driver, if this parameter is NULL, then handles
+                                   for all the children of Controller are created by this driver.
+                                   If this parameter is not NULL and the first Device Path Node is
+                                   not the End of Device Path Node, then only the handle for the
+                                   child device specified by the first Device Path Node of
+                                   RemainingDevicePath is created by this driver.
+                                   If the first Device Path Node of RemainingDevicePath is
+                                   the End of Device Path Node, no child handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been moved
+  into this common boot service. It is legal to call Stop() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+     Start() function, and the Start() function must have called OpenProtocol() on
+     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
+                                support a bus specific I/O protocol for the driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                  ControllerHandle,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer OPTIONAL
+  );
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
new file mode 100644
index 0000000..a272204
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -0,0 +1,317 @@
+/** @file
+  This driver produces XenBus Protocol instances for each Xen PV devices.
+
+  This XenBus bus driver will first initialize differente services in order to
+  enumerate the ParaVirtualized devices available.
+
+  Those services are:
+    - HyperCall
+    - Event Channel
+    - Grant Table
+    - XenStore
+    - XenBus
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <Library/DebugLib.h>
+
+#include "XenBusDxe.h"
+
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gXenBusDxeDriverBinding = {
+  XenBusDxeDriverBindingSupported,
+  XenBusDxeDriverBindingStart,
+  XenBusDxeDriverBindingStop,
+  XENBUS_DXE_VERSION,
+  NULL,
+  NULL
+};
+
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS  Status;
+
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       HandleCount;
+  UINTN       Index;
+
+  //
+  // Retrieve array of all handles in the handle database
+  //
+  Status = gBS->LocateHandleBuffer (
+                  AllHandles,
+                  NULL,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Disconnect the current driver from handles in the handle database
+  //
+  for (Index = 0; Index < HandleCount; Index++) {
+    gBS->DisconnectController (HandleBuffer[Index], gImageHandle, NULL);
+  }
+
+  //
+  // Free the array of handles
+  //
+  FreePool (HandleBuffer);
+
+
+  //
+  // Uninstall protocols installed in the driver entry point
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  ImageHandle,
+                  &gEfiDriverBindingProtocolGuid, &gXenBusDxeDriverBinding,
+                  &gEfiComponentNameProtocolGuid,  &gXenBusDxeComponentName,
+                  &gEfiComponentName2ProtocolGuid, &gXenBusDxeComponentName2,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Install UEFI Driver Model protocol(s).
+  //
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gXenBusDxeDriverBinding,
+             ImageHandle,
+             &gXenBusDxeComponentName,
+             &gXenBusDxeComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+
+  return Status;
+}
+
+
+/**
+  Tests to see if this driver supports a given controller. If a child device is provided,
+  it further tests to see if this driver supports creating a handle for the specified child device.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For bus drivers, if this parameter is not NULL, then
+                                   the bus driver must determine if the bus controller specified
+                                   by ControllerHandle and the child controller specified
+                                   by RemainingDevicePath are both supported by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by a different
+                                   driver or an application that requires exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS          Status;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  PCI_TYPE00          Pci;
+
+  Status = gBS->OpenProtocol (
+                     ControllerHandle,
+                     &gEfiPciIoProtocolGuid,
+                     (VOID **)&PciIo,
+                     This->DriverBindingHandle,
+                     ControllerHandle,
+                     EFI_OPEN_PROTOCOL_BY_DRIVER
+                     );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0,
+                            sizeof Pci / sizeof (UINT32), &Pci);
+
+  if (Status == EFI_SUCCESS) {
+    if (Pci.Hdr.VendorId == PCI_VENDOR_ID_XEN &&
+        Pci.Hdr.DeviceId == PCI_DEVICE_ID_XEN_PLATFORM) {
+      Status = EFI_SUCCESS;
+    } else {
+      Status = EFI_UNSUPPORTED;
+    }
+  }
+
+  gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle, ControllerHandle);
+
+  return Status;
+}
+
+/**
+  Starts a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service ConnectController().
+  As a result, much of the error checking on the parameters to Start() has been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver specified by This must
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For a bus driver, if this parameter is NULL, then handles
+                                   for all the children of Controller are created by this driver.
+                                   If this parameter is not NULL and the first Device Path Node is
+                                   not the End of Device Path Node, then only the handle for the
+                                   child device specified by the first Device Path Node of
+                                   RemainingDevicePath is created by this driver.
+                                   If the first Device Path Node of RemainingDevicePath is
+                                   the End of Device Path Node, no child handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Stops a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been moved
+  into this common boot service. It is legal to call Stop() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+     Start() function, and the Start() function must have called OpenProtocol() on
+     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
+                                support a bus specific I/O protocol for the driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+XenBusDxeDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN UINTN                        NumberOfChildren,
+  IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
new file mode 100644
index 0000000..952591d
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -0,0 +1,93 @@
+/** @file
+  Function declaration and internal data for XenBusDxe.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __EFI_XENBUS_DXE_H__
+#define __EFI_XENBUS_DXE_H__
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+
+
+//
+// UEFI Driver Model Protocols
+//
+#include <Protocol/DriverBinding.h>
+
+
+//
+// Consumed Protocols
+//
+#include <Protocol/PciIo.h>
+
+
+//
+// Produced Protocols
+//
+
+
+//
+// Driver Version
+//
+#define XENBUS_DXE_VERSION  0x00000010
+
+
+//
+// Protocol instances
+//
+extern EFI_DRIVER_BINDING_PROTOCOL  gXenBusDxeDriverBinding;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gXenBusDxeComponentName2;
+extern EFI_COMPONENT_NAME_PROTOCOL  gXenBusDxeComponentName;
+
+
+//
+// Include files with function prototypes
+//
+#include "DriverBinding.h"
+#include "ComponentName.h"
+
+//
+// Other stuff
+//
+#define PCI_VENDOR_ID_XEN                0x5853
+#define PCI_DEVICE_ID_XEN_PLATFORM       0x0001
+
+
+#endif
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
new file mode 100644
index 0000000..25fd2f6
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -0,0 +1,56 @@
+
+## @file
+#  TODO: Brief Description of UEFI Driver XenBusDxe
+#
+#  TODO: Detailed Description of UEFI Driver XenBusDxe
+#
+#  TODO: Copyright for UEFI Driver XenBusDxe
+#
+#  TODO: License for UEFI Driver XenBusDxe
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = XenBusDxe
+  FILE_GUID                 = 565ec8ba-a484-11e3-802b-b8ac6f7d65e6
+  MODULE_TYPE               = UEFI_DRIVER
+
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = XenBusDxeDriverEntryPoint
+  UNLOAD_IMAGE              = XenBusDxeUnload
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[Sources]
+  XenBusDxe.h
+  XenBusDxe.c
+  DriverBinding.h
+  ComponentName.c
+  ComponentName.h
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  DevicePathLib
+  DebugLib
+  HobLib
+
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid
+  gEfiPciIoProtocolGuid
+  gEfiComponentName2ProtocolGuid
+  gEfiComponentNameProtocolGuid
+
+
+[Guids]
+  gEfiXenInfoGuid
+
-- 
Anthony PERARD

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

* [PATCH v3 04/19] OvmfPkg/XenBusDxe: Add device state struct and create an ExitBoot services event.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (2 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 03/19] OvmfPkg: Add basic skeleton for the XenBus bus driver Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 05/19] OvmfPkg/XenBusDxe: Add support to make Xen Hypercalls Anthony PERARD
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

The ExitBoot event is used to disconnect from the device before the
next operating system start using them.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- use the variable mMyDevice to prevent the driver from
  starting twice (if there is two different PCI devices).
- free(dev) on exit
---
 OvmfPkg/XenBusDxe/XenBusDxe.c | 56 +++++++++++++++++++++++++++++++++++++++++--
 OvmfPkg/XenBusDxe/XenBusDxe.h | 11 +++++++++
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index a272204..8a04c8e 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -59,6 +59,9 @@ EFI_DRIVER_BINDING_PROTOCOL gXenBusDxeDriverBinding = {
 };
 
 
+STATIC EFI_LOCK       mMyDeviceLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_CALLBACK);
+STATIC XENBUS_DEVICE *mMyDevice = NULL;
+
 /**
   Unloads an image.
 
@@ -232,6 +235,19 @@ XenBusDxeDriverBindingSupported (
   return Status;
 }
 
+VOID
+EFIAPI
+NotifyExitBoot (
+  IN EFI_EVENT Event,
+  IN VOID *Context
+  )
+{
+  XENBUS_DEVICE *Dev = Context;
+
+  gBS->DisconnectController(Dev->ControllerHandle,
+                            Dev->This->DriverBindingHandle, NULL);
+}
+
 /**
   Starts a bus controller.
 
@@ -275,7 +291,37 @@ XenBusDxeDriverBindingStart (
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   )
 {
-  return EFI_UNSUPPORTED;
+  EFI_STATUS Status;
+  XENBUS_DEVICE *Dev;
+
+  Dev = AllocateZeroPool (sizeof (*Dev));
+  Dev->Signature = XENBUS_DEVICE_SIGNATURE;
+  Dev->This = This;
+  Dev->ControllerHandle = ControllerHandle;
+
+  EfiAcquireLock (&mMyDeviceLock);
+  if (mMyDevice != NULL) {
+    EfiReleaseLock (&mMyDeviceLock);
+    //
+    // There is already a XenBus running, only one can be used at a time.
+    //
+    Status = EFI_ALREADY_STARTED;
+    goto ErrorAllocated;
+  }
+  mMyDevice = Dev;
+  EfiReleaseLock (&mMyDeviceLock);
+
+  Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
+                             NotifyExitBoot,
+                             (VOID*) Dev,
+                             &Dev->ExitBootEvent);
+  ASSERT_EFI_ERROR (Status);
+
+  return EFI_SUCCESS;
+
+ErrorAllocated:
+  FreePool (Dev);
+  return Status;
 }
 
 /**
@@ -313,5 +359,11 @@ XenBusDxeDriverBindingStop (
   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
   )
 {
-  return EFI_UNSUPPORTED;
+  XENBUS_DEVICE *Dev = mMyDevice;
+
+  gBS->CloseEvent (Dev->ExitBootEvent);
+
+  mMyDevice = NULL;
+  FreePool (Dev);
+  return EFI_SUCCESS;
 }
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 952591d..8d7fe89 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -90,4 +90,15 @@ extern EFI_COMPONENT_NAME_PROTOCOL  gXenBusDxeComponentName;
 #define PCI_DEVICE_ID_XEN_PLATFORM       0x0001
 
 
+typedef struct _XENBUS_DEVICE XENBUS_DEVICE;
+
+// Have the state of the driver.
+#define XENBUS_DEVICE_SIGNATURE SIGNATURE_32 ('X','B','s','t')
+struct _XENBUS_DEVICE {
+  UINT32                        Signature;
+  EFI_DRIVER_BINDING_PROTOCOL   *This;
+  EFI_HANDLE                    ControllerHandle;
+  EFI_EVENT                     ExitBootEvent;
+};
+
 #endif
-- 
Anthony PERARD

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

* [PATCH v3 05/19] OvmfPkg/XenBusDxe: Add support to make Xen Hypercalls.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (3 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 04/19] OvmfPkg/XenBusDxe: Add device state struct and create an ExitBoot services event Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 06/19] OvmfPkg/XenBusDxe: Open PciIo protocol Anthony PERARD
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Change in V3:
- adding IA32 support. (not reviewed yet)
  both XenBusDxe/Ia32/hypercall.{S,asm} file are new

Change in V2:
- file header, copyright
- Add License
- Add push/pop instruction.
- fix types
- Comment of exported functions
- Improve coding style
- Add error handling in the main init function (of the drivers)
- Comment assembly
---
 OvmfPkg/XenBusDxe/Ia32/hypercall.S   |  22 ++++++
 OvmfPkg/XenBusDxe/Ia32/hypercall.asm |  26 +++++++
 OvmfPkg/XenBusDxe/X64/hypercall.S    |  22 ++++++
 OvmfPkg/XenBusDxe/X64/hypercall.asm  |  26 +++++++
 OvmfPkg/XenBusDxe/XenBusDxe.c        |  18 +++++
 OvmfPkg/XenBusDxe/XenBusDxe.h        |   5 ++
 OvmfPkg/XenBusDxe/XenBusDxe.inf      |  10 +++
 OvmfPkg/XenBusDxe/XenHypercall.c     | 134 +++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenHypercall.h     | 100 ++++++++++++++++++++++++++
 9 files changed, 363 insertions(+)
 create mode 100644 OvmfPkg/XenBusDxe/Ia32/hypercall.S
 create mode 100644 OvmfPkg/XenBusDxe/Ia32/hypercall.asm
 create mode 100644 OvmfPkg/XenBusDxe/X64/hypercall.S
 create mode 100644 OvmfPkg/XenBusDxe/X64/hypercall.asm
 create mode 100644 OvmfPkg/XenBusDxe/XenHypercall.c
 create mode 100644 OvmfPkg/XenBusDxe/XenHypercall.h

diff --git a/OvmfPkg/XenBusDxe/Ia32/hypercall.S b/OvmfPkg/XenBusDxe/Ia32/hypercall.S
new file mode 100644
index 0000000..d2b4167
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/Ia32/hypercall.S
@@ -0,0 +1,22 @@
+# INTN
+# EFIAPI
+# XenHypercall2 (
+#   IN     VOID *HypercallAddr,
+#   IN OUT INTN Arg1,
+#   IN OUT INTN Arg2
+#   );
+ASM_GLOBAL ASM_PFX(XenHypercall2)
+ASM_PFX(XenHypercall2):
+  # Save only ebx, ecx is supposed to be a scratch register and needs to be
+  # saved by the caller
+  push %ebx
+  # Copy HypercallAddr to eax
+  mov 8(%esp), %eax
+  # Copy Arg1 to the register expected by Xen
+  mov 12(%esp), %ebx
+  # Copy Arg2 to the register expected by Xen
+  mov 16(%esp), %ecx
+  # Call HypercallAddr
+  call *%eax
+  pop %ebx
+  ret
diff --git a/OvmfPkg/XenBusDxe/Ia32/hypercall.asm b/OvmfPkg/XenBusDxe/Ia32/hypercall.asm
new file mode 100644
index 0000000..0fff9a2
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/Ia32/hypercall.asm
@@ -0,0 +1,26 @@
+.code
+
+; INTN
+; EFIAPI
+; XenHypercall2 (
+;   IN     VOID *HypercallAddr,
+;   IN OUT INTN Arg1,
+;   IN OUT INTN Arg2
+;   );
+XenHypercall2 PROC
+  ; Save only ebx, ecx is supposed to be a scratch register and needs to be
+  ; saved by the caller
+  push ebx
+  ; Copy HypercallAddr to eax
+  mov eax, [esp + 8]
+  ; Copy Arg1 to the register expected by Xen
+  mov ebx, [esp + 12]
+  ; Copy Arg2 to the register expected by Xen
+  mov ecx, [esp + 16]
+  ; Call HypercallAddr
+  call eax
+  pop ebx
+  ret
+XenHypercall2 ENDP
+
+END
diff --git a/OvmfPkg/XenBusDxe/X64/hypercall.S b/OvmfPkg/XenBusDxe/X64/hypercall.S
new file mode 100644
index 0000000..a167917
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/X64/hypercall.S
@@ -0,0 +1,22 @@
+# INTN
+# EFIAPI
+# XenHypercall2 (
+#   IN     VOID *HypercallAddr,
+#   IN OUT INTN Arg1,
+#   IN OUT INTN Arg2
+#   );
+ASM_GLOBAL ASM_PFX(XenHypercall2)
+ASM_PFX(XenHypercall2):
+  push %rdi
+  push %rsi
+  # Copy HypercallAddr to rax
+  movq %rcx, %rax
+  # Copy Arg1 to the register expected by Xen
+  movq %rdx, %rdi
+  # Copy Arg2 to the register expected by Xen
+  movq %r8, %rsi
+  # Call HypercallAddr
+  call *%rax
+  pop %rsi
+  pop %rdi
+  ret
diff --git a/OvmfPkg/XenBusDxe/X64/hypercall.asm b/OvmfPkg/XenBusDxe/X64/hypercall.asm
new file mode 100644
index 0000000..c11c3e5
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/X64/hypercall.asm
@@ -0,0 +1,26 @@
+.code
+
+; INTN
+; EFIAPI
+; XenHypercall2 (
+;   IN     VOID *HypercallAddr,
+;   IN OUT INTN Arg1,
+;   IN OUT INTN Arg2
+;   );
+XenHypercall2 PROC
+  push rdi
+  push rsi
+  ; Copy HypercallAddr to rax
+  mov rax, rcx
+  ; Copy Arg1 to the register expected by Xen
+  mov rdi, rdx
+  ; Copy Arg2 to the register expected by Xen
+  mov rsi, r8
+  ; Call HypercallAddr
+  call rax
+  pop rsi
+  pop rdi
+  ret
+XenHypercall2 ENDP
+
+END
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index 8a04c8e..d764365 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -45,6 +45,8 @@
 
 #include "XenBusDxe.h"
 
+#include "XenHypercall.h"
+
 
 ///
 /// Driver Binding Protocol instance
@@ -280,6 +282,8 @@ NotifyExitBoot (
   @retval EFI_SUCCESS              The device was started.
   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval EFI_UNSUPPORTED          Something is missing on the system that
+                                   prevent to start the edvice.
   @retval Others                   The driver failded to start the device.
 
 **/
@@ -311,6 +315,20 @@ XenBusDxeDriverBindingStart (
   mMyDevice = Dev;
   EfiReleaseLock (&mMyDeviceLock);
 
+  Status = XenHyperpageInit (Dev);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.\n"));
+    Status = EFI_UNSUPPORTED;
+    goto ErrorAllocated;
+  }
+
+  Status = XenGetSharedInfoPage (Dev);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XenBus: Unable to get the shared info page.\n"));
+    Status = EFI_UNSUPPORTED;
+    goto ErrorAllocated;
+  }
+
   Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
                              NotifyExitBoot,
                              (VOID*) Dev,
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 8d7fe89..0b27699 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -86,6 +86,8 @@ extern EFI_COMPONENT_NAME_PROTOCOL  gXenBusDxeComponentName;
 //
 // Other stuff
 //
+#include <IndustryStandard/Xen/xen.h>
+
 #define PCI_VENDOR_ID_XEN                0x5853
 #define PCI_DEVICE_ID_XEN_PLATFORM       0x0001
 
@@ -99,6 +101,9 @@ struct _XENBUS_DEVICE {
   EFI_DRIVER_BINDING_PROTOCOL   *This;
   EFI_HANDLE                    ControllerHandle;
   EFI_EVENT                     ExitBootEvent;
+
+  VOID                          *Hyperpage;
+  shared_info_t                 *SharedInfo;
 };
 
 #endif
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index 25fd2f6..b824d63 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -31,6 +31,16 @@
   DriverBinding.h
   ComponentName.c
   ComponentName.h
+  XenHypercall.c
+  XenHypercall.h
+
+[Sources.IA32]
+  Ia32/hypercall.S
+  Ia32/hypercall.asm
+
+[Sources.X64]
+  X64/hypercall.S
+  X64/hypercall.asm
 
 [LibraryClasses]
   UefiDriverEntryPoint
diff --git a/OvmfPkg/XenBusDxe/XenHypercall.c b/OvmfPkg/XenBusDxe/XenHypercall.c
new file mode 100644
index 0000000..1b4dc14
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenHypercall.c
@@ -0,0 +1,134 @@
+/** @file
+  Functions to make Xen hypercalls.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include <PiDxe.h>
+#include <Library/HobLib.h>
+#include <Guid/XenInfo.h>
+
+#include "XenBusDxe.h"
+#include "XenHypercall.h"
+
+#include <IndustryStandard/Xen/hvm/params.h>
+#include <IndustryStandard/Xen/memory.h>
+
+EFI_STATUS
+XenHyperpageInit (
+  IN OUT XENBUS_DEVICE *Dev
+  )
+{
+  EFI_HOB_GUID_TYPE   *GuidHob;
+  EFI_XEN_INFO        *XenInfo;
+
+  GuidHob = GetFirstGuidHob (&gEfiXenInfoGuid);
+  if (GuidHob == NULL) {
+    return EFI_NOT_FOUND;
+  }
+  XenInfo = (EFI_XEN_INFO *) GET_GUID_HOB_DATA (GuidHob);
+  Dev->Hyperpage = XenInfo->HyperPages;
+  return EFI_SUCCESS;
+}
+
+UINT64
+XenHypercallHvmGetParam (
+  IN XENBUS_DEVICE *Dev,
+  IN INTN          Index
+  )
+{
+  xen_hvm_param_t     Parameter;
+  INTN                Error;
+
+  ASSERT (Dev->Hyperpage != NULL);
+
+  Parameter.domid = DOMID_SELF;
+  Parameter.index = Index;
+  Error = XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_hvm_op * 32,
+                         HVMOP_get_param, (INTN) &Parameter);
+  if (Error != 0) {
+    DEBUG ((EFI_D_ERROR,
+            "XenHypercall: Error %d trying to get HVM parameter %d\n",
+            Error, Index));
+    return 0;
+  }
+  return Parameter.value;
+}
+
+INTN
+XenHypercallMemoryOp (
+  IN     XENBUS_DEVICE *Dev,
+  IN     UINTN Operation,
+  IN OUT VOID *Arguments
+  )
+{
+  ASSERT (Dev->Hyperpage != NULL);
+  return XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_memory_op * 32,
+                        Operation, (INTN) Arguments);
+}
+
+INTN
+XenHypercallEventChannelOp (
+  IN     XENBUS_DEVICE *Dev,
+  IN     INTN Operation,
+  IN OUT VOID *Arguments
+  )
+{
+  ASSERT (Dev->Hyperpage != NULL);
+  return XenHypercall2 (Dev->Hyperpage + __HYPERVISOR_event_channel_op * 32,
+                        Operation, (INTN) Arguments);
+}
+
+EFI_STATUS
+XenGetSharedInfoPage (
+  IN OUT XENBUS_DEVICE *Dev
+  )
+{
+  xen_add_to_physmap_t Parameter;
+
+  ASSERT (Dev->SharedInfo == NULL);
+
+  Parameter.domid = DOMID_SELF;
+  Parameter.space = XENMAPSPACE_shared_info;
+  Parameter.idx = 0;
+
+  //
+  // using reserved page because the page is not released when Linux is
+  // starting because of the add_to_physmap. QEMU might try to access the
+  // page, and fail because it have no right to do so (segv).
+  //
+  Dev->SharedInfo = AllocateReservedPages (1);
+  Parameter.gpfn = (UINTN) Dev->SharedInfo >> EFI_PAGE_SHIFT;
+  if (XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameter) != 0) {
+    FreePages (Dev->SharedInfo, 1);
+    Dev->SharedInfo = NULL;
+    return EFI_LOAD_ERROR;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/XenBusDxe/XenHypercall.h b/OvmfPkg/XenBusDxe/XenHypercall.h
new file mode 100644
index 0000000..29eaf9f
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenHypercall.h
@@ -0,0 +1,100 @@
+#ifndef __XENBUS_DXE_HYPERCALL_H__
+#define __XENBUS_DXE_HYPERCALL_H__
+
+typedef struct _XENBUS_DEVICE XENBUS_DEVICE;
+
+/**
+  This function will put the two arguments in the right place (registers) and
+  call HypercallAddr, which correspond to an entry in the hypercall pages.
+
+  @param HypercallAddr  A memory address where the hypercall to call is.
+  @param Arg1           First argument.
+  @param Arg2           Second argument.
+
+  @return   Return 0 if success otherwise it return an errno.
+**/
+INTN
+EFIAPI
+XenHypercall2 (
+  IN     VOID *HypercallAddr,
+  IN OUT INTN Arg1,
+  IN OUT INTN Arg2
+  );
+
+/**
+  Get the page where all hypercall are from the XenInfo hob.
+
+  @param Dev    A XENBUS_DEVICE instance.
+
+  @retval EFI_NOT_FOUND   hyperpage could not be found.
+  @retval EFI_SUCCESS     Successfully retrieve the hyperpage pointer.
+**/
+EFI_STATUS
+XenHyperpageInit (
+  XENBUS_DEVICE *Dev
+  );
+
+/**
+  Return the value of the HVM parameter Index.
+
+  @param Dev    A XENBUS_DEVICE instance.
+  @param Index  The parameter to get, e.g. HVM_PARAM_STORE_EVTCHN.
+
+  @return   The value of the asked parameter or 0 in case of error.
+**/
+UINT64
+XenHypercallHvmGetParam (
+  XENBUS_DEVICE *Dev,
+  INTN Index
+  );
+
+/**
+  Hypercall to do different operation on the memory.
+
+  @param Dev        A XENBUS_DEVICE instance.
+  @param Operation  The operation number, e.g. XENMEM_add_to_physmap.
+  @param Arguments  The arguments associated to the operation.
+
+  @return  Return the return value from the hypercall, 0 in case of success
+           otherwise, an error code.
+**/
+INTN
+XenHypercallMemoryOp (
+  IN     XENBUS_DEVICE *Dev,
+  IN     UINTN Operation,
+  IN OUT VOID *Arguments
+  );
+
+/**
+  Do an operation on the event channels.
+
+  @param Dev        A XENBUS_DEVICE instance.
+  @param Operation  The operation number, e.g. EVTCHNOP_send.
+  @param Arguments  The argument associated to the operation.
+
+  @return  Return the return value from the hypercall, 0 in case of success
+           otherwise, an error code.
+**/
+INTN
+XenHypercallEventChannelOp (
+  IN     XENBUS_DEVICE *Dev,
+  IN     INTN Operation,
+  IN OUT VOID *Arguments
+  );
+
+/**
+  Map the shared_info_t page into memory.
+
+  @param Dev    A XENBUS_DEVICE instance.
+
+  @retval EFI_SUCCESS     Dev->SharedInfo whill contain a pointer to
+                          the shared info page
+  @retval EFI_LOAD_ERROR  The shared info page could not be mapped. The
+                          hypercall returned an error.
+**/
+EFI_STATUS
+XenGetSharedInfoPage (
+  IN OUT XENBUS_DEVICE *Dev
+  );
+
+#endif
-- 
Anthony PERARD

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

* [PATCH v3 06/19] OvmfPkg/XenBusDxe: Open PciIo protocol.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (4 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 05/19] OvmfPkg/XenBusDxe: Add support to make Xen Hypercalls Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 07/19] OvmfPkg: Introduce XenBus Protocol Anthony PERARD
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

The PciIo interface will be used in "OvmfPkg/XenBusDxe: Add Grant Table
functions" to get the memory address of the BAR 1 and use the space to
map shared memory.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- add a commit description.

Change in V2:
- Coding style
- Error handler
---
 OvmfPkg/XenBusDxe/XenBusDxe.c | 19 +++++++++++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index d764365..b8766fe 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -297,11 +297,25 @@ XenBusDxeDriverBindingStart (
 {
   EFI_STATUS Status;
   XENBUS_DEVICE *Dev;
+  EFI_PCI_IO_PROTOCOL *PciIo;
+
+  Status = gBS->OpenProtocol (
+                     ControllerHandle,
+                     &gEfiPciIoProtocolGuid,
+                     (VOID **) &PciIo,
+                     This->DriverBindingHandle,
+                     ControllerHandle,
+                     EFI_OPEN_PROTOCOL_BY_DRIVER
+                     );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
 
   Dev = AllocateZeroPool (sizeof (*Dev));
   Dev->Signature = XENBUS_DEVICE_SIGNATURE;
   Dev->This = This;
   Dev->ControllerHandle = ControllerHandle;
+  Dev->PciIo = PciIo;
 
   EfiAcquireLock (&mMyDeviceLock);
   if (mMyDevice != NULL) {
@@ -339,6 +353,8 @@ XenBusDxeDriverBindingStart (
 
 ErrorAllocated:
   FreePool (Dev);
+  gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
+                      This->DriverBindingHandle, ControllerHandle);
   return Status;
 }
 
@@ -381,6 +397,9 @@ XenBusDxeDriverBindingStop (
 
   gBS->CloseEvent (Dev->ExitBootEvent);
 
+  gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
+         This->DriverBindingHandle, ControllerHandle);
+
   mMyDevice = NULL;
   FreePool (Dev);
   return EFI_SUCCESS;
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 0b27699..56453ad 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -100,6 +100,7 @@ struct _XENBUS_DEVICE {
   UINT32                        Signature;
   EFI_DRIVER_BINDING_PROTOCOL   *This;
   EFI_HANDLE                    ControllerHandle;
+  EFI_PCI_IO_PROTOCOL           *PciIo;
   EFI_EVENT                     ExitBootEvent;
 
   VOID                          *Hyperpage;
-- 
Anthony PERARD

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

* [PATCH v3 07/19] OvmfPkg: Introduce XenBus Protocol.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (5 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 06/19] OvmfPkg/XenBusDxe: Open PciIo protocol Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 08/19] OvmfPkg/XenBusDxe: Add InterlockedCompareExchange16 Anthony PERARD
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This protocol will be used for communication between a PV driver (like a
PV block driver) and the XenBus/XenStore.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

--
Change in V3:
- Add disclaimer about the volatile nature of the protocol.
- Add a description on the two introduced members to the protocol.

Change in V2:
- Comment, file header
- Protocol License
- Declare xen interface version earlier
- Rename protocol from Xenbus to XenBus
---
 OvmfPkg/Include/Protocol/XenBus.h | 108 ++++++++++++++++++++++++++++++++++++++
 OvmfPkg/OvmfPkg.dec               |   1 +
 OvmfPkg/XenBusDxe/XenBusDxe.h     |   6 +++
 OvmfPkg/XenBusDxe/XenBusDxe.inf   |   1 +
 4 files changed, 116 insertions(+)
 create mode 100644 OvmfPkg/Include/Protocol/XenBus.h

diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h
new file mode 100644
index 0000000..03d23bf
--- /dev/null
+++ b/OvmfPkg/Include/Protocol/XenBus.h
@@ -0,0 +1,108 @@
+
+/** @file
+  XenBus protocol to be used between the XenBus bus driver and Xen PV devices.
+
+  DISCLAIMER: the XENBUS_PROTOCOL introduced here is a work in progress, and
+  should not be used outside of the EDK II tree.
+
+  This protocol provide the necessary for a Xen PV driver frontend to
+  communicate with the bus driver, and perform several task to
+  initialize/shutdown a PV device and perform IO with a PV backend.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __PROTOCOL_XENBUS_H__
+#define __PROTOCOL_XENBUS_H__
+
+#define XENBUS_PROTOCOL_GUID \
+  {0x3d3ca290, 0xb9a5, 0x11e3, {0xb7, 0x5d, 0xb8, 0xac, 0x6f, 0x7d, 0x65, 0xe6}}
+
+///
+/// Forward declaration
+///
+typedef struct _XENBUS_PROTOCOL XENBUS_PROTOCOL;
+
+
+#include <IndustryStandard/Xen/grant_table.h>
+
+///
+/// Function prototypes
+///
+
+/**
+  Grant access to the page Frame to the domain DomainId.
+
+  @param This       A pointer to XENBUS_PROTOCOL instance.
+  @param DomainId   ID of the domain to grant acces to.
+  @param Frame      Frame Number of the page to grant access to.
+  @param ReadOnly   Provide read-only or read-write access.
+  @param RefPtr     Reference number of the grant will be writen to this pointer.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *XENBUS_GRANT_ACCESS)(
+  IN  XENBUS_PROTOCOL *This,
+  IN  domid_t         DomainId,
+  IN  UINTN           Frame,
+  IN  BOOLEAN         ReadOnly,
+  OUT grant_ref_t     *refp
+  );
+
+/**
+  End access to grant Ref, previously return by XenBusGrantAccess.
+
+  @param This       A pointer to XENBUS_PROTOCOL instance.
+  @param Ref        Reference numeber of a grant previously returned by
+                    XenBusGrantAccess.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *XENBUS_GRANT_END_ACCESS)(
+  IN XENBUS_PROTOCOL  *This,
+  IN grant_ref_t      Ref
+  );
+
+
+///
+/// Protocol structure
+///
+/// DISCLAIMER: the XENBUS_PROTOCOL introduced here is a work in progress, and
+/// should not be used outside of the EDK II tree.
+///
+struct _XENBUS_PROTOCOL {
+  XENBUS_GRANT_ACCESS           GrantAccess;
+  XENBUS_GRANT_END_ACCESS       GrantEndAccess;
+  //
+  // Protocol data fields
+  //
+};
+
+extern EFI_GUID gXenBusProtocolGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index f829247..104a7b2 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -47,6 +47,7 @@
 [Protocols]
   gVirtioDeviceProtocolGuid       = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
   gBlockMmioProtocolGuid          = {0x6b558ce3, 0x69e5, 0x4c67, {0xa6, 0x34, 0xf7, 0xfe, 0x72, 0xad, 0xbe, 0x84}}
+  gXenBusProtocolGuid             = {0x3d3ca290, 0xb9a5, 0x11e3, {0xb7, 0x5d, 0xb8, 0xac, 0x6f, 0x7d, 0x65, 0xe6}}
 
 [PcdsFixedAtBuild]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 56453ad..d286c35 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -35,6 +35,11 @@
 #include <Uefi.h>
 
 //
+// Xen interface version used
+//
+#define  __XEN_INTERFACE_VERSION__ 0x00040400
+
+//
 // Libraries
 //
 #include <Library/UefiBootServicesTableLib.h>
@@ -61,6 +66,7 @@
 //
 // Produced Protocols
 //
+#include <Protocol/XenBus.h>
 
 
 //
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index b824d63..e5bfff6 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -59,6 +59,7 @@
   gEfiPciIoProtocolGuid
   gEfiComponentName2ProtocolGuid
   gEfiComponentNameProtocolGuid
+  gXenBusProtocolGuid
 
 
 [Guids]
-- 
Anthony PERARD

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

* [PATCH v3 08/19] OvmfPkg/XenBusDxe: Add InterlockedCompareExchange16.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (6 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 07/19] OvmfPkg: Introduce XenBus Protocol Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 09/19] OvmfPkg/XenBusDxe: Add Grant Table functions Anthony PERARD
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This patch is inspired by InterlockedCompareExchange32 from the
BaseSynchronizationLib.

The function will be used in the "OvmfPkg/XenBusDxe: Add Grant Table
functions" patch.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- Implement both .S and .asm, to get rid of GCC specific asm.
- Implement 32bit part of the assembly

Change in V2:
- Add intel compilation code
  MSFT code is not compied over because I don't know how it works.
---
 .../XenBusDxe/Ia32/InterlockedCompareExchange16.S  | 15 ++++++++
 .../Ia32/InterlockedCompareExchange16.asm          | 45 ++++++++++++++++++++++
 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c   | 33 ++++++++++++++++
 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h   | 38 ++++++++++++++++++
 .../XenBusDxe/X64/InterlockedCompareExchange16.S   | 13 +++++++
 .../XenBusDxe/X64/InterlockedCompareExchange16.asm | 41 ++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.inf                    |  6 +++
 7 files changed, 191 insertions(+)
 create mode 100644 OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S
 create mode 100644 OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm
 create mode 100644 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
 create mode 100644 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
 create mode 100644 OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S
 create mode 100644 OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm

diff --git a/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S
new file mode 100644
index 0000000..b4adb66
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S
@@ -0,0 +1,15 @@
+# UINT16
+# EFIAPI
+# InternalSyncCompareExchange16 (
+#   IN      volatile UINT16           *Value,
+#   IN      UINT16                    CompareValue,
+#   IN      UINT16                    ExchangeValue
+#   );
+ASM_GLOBAL ASM_PFX(InternalSyncCompareExchange16)
+ASM_PFX(InternalSyncCompareExchange16):
+  mov 4(%esp), %ecx
+  mov 8(%esp), %eax
+  mov 12(%esp), %edx
+  lock
+  cmpxchgw %dx, (%ecx)
+  ret
diff --git a/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm
new file mode 100644
index 0000000..adcfbd0
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm
@@ -0,0 +1,45 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution.  The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .486
+    .model  flat,C
+    .code
+
+;------------------------------------------------------------------------------
+; UINT32
+; EFIAPI
+; InternalSyncCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     ecx, [esp + 4]
+    mov     eax, [esp + 8]
+    mov     edx, [esp + 12]
+    lock    cmpxchg [ecx], dx
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
new file mode 100644
index 0000000..89d96d1
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
@@ -0,0 +1,33 @@
+#include <Library/DebugLib.h>
+#include "InterlockedCompareExchange16.h"
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  )
+{
+  ASSERT (Value != NULL);
+  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
+}
diff --git a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
new file mode 100644
index 0000000..e863dbd
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
@@ -0,0 +1,38 @@
+/**
+  Assembly implementation of InterlockedCompareExchange16.
+
+  Look at the documentation of InterlockedCompareExchange16.
+**/
+UINT16
+EFIAPI
+InternalSyncCompareExchange16 (
+  IN      volatile UINT16           *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
+
+/**
+  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
+
+  Performs an atomic compare exchange operation on the 16-bit unsigned integer
+  specified by Value.  If Value is equal to CompareValue, then Value is set to
+  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
+  then Value is returned.  The compare exchange operation must be performed using
+  MP safe mechanisms.
+
+  If Value is NULL, then ASSERT().
+
+  @param  Value         A pointer to the 16-bit value for the compare exchange
+                        operation.
+  @param  CompareValue  16-bit value used in compare operation.
+  @param  ExchangeValue 16-bit value used in exchange operation.
+
+  @return The original *Value before exchange.
+**/
+UINT16
+EFIAPI
+InterlockedCompareExchange16 (
+  IN OUT  UINT16                    *Value,
+  IN      UINT16                    CompareValue,
+  IN      UINT16                    ExchangeValue
+  );
diff --git a/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S
new file mode 100644
index 0000000..c6336ca
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S
@@ -0,0 +1,13 @@
+# UINT16
+# EFIAPI
+# InternalSyncCompareExchange16 (
+#   IN      volatile UINT16           *Value,
+#   IN      UINT16                    CompareValue,
+#   IN      UINT16                    ExchangeValue
+#   );
+ASM_GLOBAL ASM_PFX(InternalSyncCompareExchange16)
+ASM_PFX(InternalSyncCompareExchange16):
+  mov %edx, %eax
+  lock
+  cmpxchgw %r8w, (%rcx)
+  ret
diff --git a/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm
new file mode 100644
index 0000000..b23e421
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm
@@ -0,0 +1,41 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+; This program and the accompanying materials
+; are licensed and made available under the terms and conditions of the BSD License
+; which accompanies this distribution.  The full text of the license may be found at
+; http://opensource.org/licenses/bsd-license.php.
+;
+; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+;
+; Module Name:
+;
+;   InterlockedCompareExchange16.Asm
+;
+; Abstract:
+;
+;   InterlockedCompareExchange16 function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+    .code
+
+;------------------------------------------------------------------------------
+; UINT16
+; EFIAPI
+; InterlockedCompareExchange16 (
+;   IN      UINT16                    *Value,
+;   IN      UINT16                    CompareValue,
+;   IN      UINT16                    ExchangeValue
+;   );
+;------------------------------------------------------------------------------
+InternalSyncCompareExchange16   PROC
+    mov     eax, edx
+    lock    cmpxchg [rcx], r8w
+    ret
+InternalSyncCompareExchange16   ENDP
+
+    END
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index e5bfff6..444118a 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -33,14 +33,20 @@
   ComponentName.h
   XenHypercall.c
   XenHypercall.h
+  InterlockedCompareExchange16.c
+  InterlockedCompareExchange16.h
 
 [Sources.IA32]
   Ia32/hypercall.S
   Ia32/hypercall.asm
+  Ia32/InterlockedCompareExchange16.S
+  Ia32/InterlockedCompareExchange16.asm
 
 [Sources.X64]
   X64/hypercall.S
   X64/hypercall.asm
+  X64/InterlockedCompareExchange16.S
+  X64/InterlockedCompareExchange16.asm
 
 [LibraryClasses]
   UefiDriverEntryPoint
-- 
Anthony PERARD

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

* [PATCH v3 09/19] OvmfPkg/XenBusDxe: Add Grant Table functions.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (7 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 08/19] OvmfPkg/XenBusDxe: Add InterlockedCompareExchange16 Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 10/19] OvmfPkg/XenBusDxe: Add Event Channel Notify Anthony PERARD
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Steven Smith, Grzegorz Milos, Xen Devel

There are used to grant access of pages to other Xen domains.

This code originaly comes from the Xen Project, and more precisely from
MiniOS.

Signed-off-by: Steven Smith <sos22@cam.ac.uk>
Signed-off-by: Grzegorz Milos <gm281@cam.ac.uk>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Change in V3:
- Add a comment about the use of the BAR of the device.

Change in V2:
- Adding locks
- Redo the file header
- Add functions comment
- Add license
---
 OvmfPkg/XenBusDxe/GrantTable.c  | 217 ++++++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/GrantTable.h  |  68 +++++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.c   |  20 ++++
 OvmfPkg/XenBusDxe/XenBusDxe.inf |   2 +
 4 files changed, 307 insertions(+)
 create mode 100644 OvmfPkg/XenBusDxe/GrantTable.c
 create mode 100644 OvmfPkg/XenBusDxe/GrantTable.h

diff --git a/OvmfPkg/XenBusDxe/GrantTable.c b/OvmfPkg/XenBusDxe/GrantTable.c
new file mode 100644
index 0000000..8b08134
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/GrantTable.c
@@ -0,0 +1,217 @@
+/** @file
+  Grant Table function implementation.
+
+  Grant Table are used to grant access to certain page of the current
+  VM to an other VM.
+
+  Author: Steven Smith (sos22@cam.ac.uk)
+  Changes: Grzegorz Milos (gm281@cam.ac.uk)
+  Copyright (C) 2006, Cambridge University
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  SUCH DAMAGE.
+**/
+#include "XenBusDxe.h"
+
+#include <IndustryStandard/Xen/memory.h>
+
+#include "XenHypercall.h"
+
+#include "GrantTable.h"
+#include "InterlockedCompareExchange16.h"
+
+#define NR_RESERVED_ENTRIES 8
+
+/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */
+#define NR_GRANT_FRAMES 4
+#define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * EFI_PAGE_SIZE / sizeof(grant_entry_v1_t))
+
+STATIC grant_entry_v1_t *GrantTable = NULL;
+STATIC grant_ref_t GrantList[NR_GRANT_ENTRIES];
+STATIC EFI_LOCK mGrantListLock;
+#ifdef GNT_DEBUG
+STATIC BOOLEAN GrantInUseList[NR_GRANT_ENTRIES];
+#endif
+
+STATIC
+VOID
+XenGrantTablePutFreeEntry (
+  grant_ref_t Ref
+  )
+{
+  EfiAcquireLock (&mGrantListLock);
+#ifdef GNT_DEBUG
+  ASSERT (GrantInUseList[Ref]);
+  GrantInUseList[Ref] = FALSE;
+#endif
+  GrantList[Ref] = GrantList[0];
+  GrantList[0] = Ref;
+  EfiReleaseLock (&mGrantListLock);
+}
+
+STATIC
+grant_ref_t
+XenGrantTableGetFreeEntry (
+  VOID
+  )
+{
+  UINTN Ref;
+
+  EfiAcquireLock (&mGrantListLock);
+  Ref = GrantList[0];
+  ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
+  GrantList[0] = GrantList[Ref];
+#ifdef GNT_DEBUG
+  ASSERT (!GrantInUseList[Ref]);
+  GrantInUseList[Ref] = TRUE;
+#endif
+  EfiReleaseLock (&mGrantListLock);
+  return Ref;
+}
+
+STATIC
+grant_ref_t
+XenGrantTableGrantAccess (
+  IN domid_t  DomainId,
+  IN UINTN    Frame,
+  IN BOOLEAN  ReadOnly
+  )
+{
+  grant_ref_t Ref;
+  UINT32 Flags;
+
+  ASSERT (GrantTable != NULL);
+  Ref = XenGrantTableGetFreeEntry ();
+  GrantTable[Ref].frame = Frame;
+  GrantTable[Ref].domid = DomainId;
+  MemoryFence ();
+  Flags = GTF_permit_access;
+  if (ReadOnly) {
+    Flags |= GTF_readonly;
+  }
+  GrantTable[Ref].flags = Flags;
+
+  return Ref;
+}
+
+STATIC
+EFI_STATUS
+XenGrantTableEndAccess (
+  grant_ref_t Ref
+  )
+{
+  UINT16 Flags, OldFlags;
+
+  ASSERT (GrantTable != NULL);
+  ASSERT (Ref >= NR_RESERVED_ENTRIES && Ref < NR_GRANT_ENTRIES);
+
+  OldFlags = GrantTable[Ref].flags;
+  do {
+    if ((Flags = OldFlags) & (GTF_reading | GTF_writing)) {
+      DEBUG ((EFI_D_WARN, "WARNING: g.e. still in use! (%x)\n", Flags));
+      return EFI_NOT_READY;
+    }
+    OldFlags = InterlockedCompareExchange16 (&GrantTable[Ref].flags, Flags, 0);
+  } while (OldFlags != Flags);
+
+  XenGrantTablePutFreeEntry (Ref);
+  return EFI_SUCCESS;
+}
+
+VOID
+XenGrantTableInit (
+  IN XENBUS_DEVICE  *Dev,
+  IN UINT64         MmioAddr
+  )
+{
+  xen_add_to_physmap_t Parameters;
+  INTN Index;
+  INTN ReturnCode;
+
+#ifdef GNT_DEBUG
+  SetMem(GrantInUseList, sizeof (GrantInUseList), 1);
+#endif
+  EfiInitializeLock (&mGrantListLock, TPL_NOTIFY);
+  for (Index = NR_RESERVED_ENTRIES; Index < NR_GRANT_ENTRIES; Index++) {
+    XenGrantTablePutFreeEntry (Index);
+  }
+
+  GrantTable = (VOID*)(UINTN) MmioAddr;
+  for (Index = 0; Index < NR_GRANT_FRAMES; Index++) {
+    Parameters.domid = DOMID_SELF;
+    Parameters.idx = Index;
+    Parameters.space = XENMAPSPACE_grant_table;
+    Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
+    ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_add_to_physmap, &Parameters);
+    if (ReturnCode != 0) {
+      DEBUG ((EFI_D_ERROR, "Xen GrantTable, add_to_physmap hypercall error: %d\n", ReturnCode));
+    }
+  }
+}
+
+VOID
+XenGrantTableDeinit (
+  XENBUS_DEVICE *Dev
+  )
+{
+  INTN ReturnCode, Index;
+  xen_remove_from_physmap_t Parameters;
+
+  if (GrantTable == NULL) {
+    return;
+  }
+
+  for (Index = NR_GRANT_FRAMES - 1; Index >= 0; Index--) {
+    Parameters.domid = DOMID_SELF;
+    Parameters.gpfn = (((xen_pfn_t) GrantTable) >> EFI_PAGE_SHIFT) + Index;
+    DEBUG ((EFI_D_INFO, "Xen GrantTable, removing %X\n", Parameters.gpfn));
+    ReturnCode = XenHypercallMemoryOp (Dev, XENMEM_remove_from_physmap, &Parameters);
+    if (ReturnCode != 0) {
+      DEBUG ((EFI_D_ERROR, "Xen GrantTable, remove_from_physmap hypercall error: %d\n", ReturnCode));
+    }
+  }
+  GrantTable = NULL;
+}
+
+EFI_STATUS
+EFIAPI
+XenBusGrantAccess (
+  IN  XENBUS_PROTOCOL *This,
+  IN  domid_t         DomainId,
+  IN  UINTN           Frame, // MFN
+  IN  BOOLEAN         ReadOnly,
+  OUT grant_ref_t     *RefPtr
+  )
+{
+  *RefPtr = XenGrantTableGrantAccess (DomainId, Frame, ReadOnly);
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+XenBusGrantEndAccess (
+  IN XENBUS_PROTOCOL  *This,
+  IN grant_ref_t      Ref
+  )
+{
+  return XenGrantTableEndAccess (Ref);
+}
diff --git a/OvmfPkg/XenBusDxe/GrantTable.h b/OvmfPkg/XenBusDxe/GrantTable.h
new file mode 100644
index 0000000..bbead2e
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/GrantTable.h
@@ -0,0 +1,68 @@
+/** @file
+  Grant Table function declaration.
+
+  Grant Table are used to grant access to certain page of the current
+  VM to an other VM.
+
+  Copyright (C) 2014, Citrix Ltd.
+**/
+#ifndef __GNTTAB_H__
+#define __GNTTAB_H__
+
+#include <IndustryStandard/Xen/grant_table.h>
+
+/**
+  Initialize the Grant Table at the address MmioAddr.
+
+  @param Dev      A pointer to XENBUS_DEVICE.
+  @param MmioAddr An address where the grant table can be mapped into
+                  the guest.
+**/
+VOID
+XenGrantTableInit (
+  IN XENBUS_DEVICE  *Dev,
+  IN UINT64         MmioAddr
+  );
+
+/**
+  Desinitilize the Grant Table.
+**/
+VOID
+XenGrantTableDeinit (
+  IN XENBUS_DEVICE  *Dev
+  );
+
+/**
+  Grant access to the page Frame to the domain DomainId.
+
+  @param This       A pointer to XENBUS_PROTOCOL instance.
+  @param DomainId   ID of the domain to grant acces to.
+  @param Frame      Frame Number of the page to grant access to.
+  @param ReadOnly   Provide read-only or read-write access.
+  @param RefPtr     Reference number of the grant will be writen to this pointer.
+**/
+EFI_STATUS
+EFIAPI
+XenBusGrantAccess (
+  IN  XENBUS_PROTOCOL *This,
+  IN  domid_t         DomainId,
+  IN  UINTN           Frame, // MFN
+  IN  BOOLEAN         ReadOnly,
+  OUT grant_ref_t     *RefPtr
+  );
+
+/**
+  End access to grant Ref, previously return by XenBusGrantAccess.
+
+  @param This       A pointer to XENBUS_PROTOCOL instance.
+  @param Ref        Reference numeber of a grant previously returned by
+                    XenBusGrantAccess.
+**/
+EFI_STATUS
+EFIAPI
+XenBusGrantEndAccess (
+  IN XENBUS_PROTOCOL  *This,
+  IN grant_ref_t      Ref
+  );
+
+#endif /* !__GNTTAB_H__ */
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index b8766fe..fa267b6 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -46,6 +46,7 @@
 #include "XenBusDxe.h"
 
 #include "XenHypercall.h"
+#include "GrantTable.h"
 
 
 ///
@@ -298,6 +299,8 @@ XenBusDxeDriverBindingStart (
   EFI_STATUS Status;
   XENBUS_DEVICE *Dev;
   EFI_PCI_IO_PROTOCOL *PciIo;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
+  UINT64 MmioAddr;
 
   Status = gBS->OpenProtocol (
                      ControllerHandle,
@@ -329,6 +332,20 @@ XenBusDxeDriverBindingStart (
   mMyDevice = Dev;
   EfiReleaseLock (&mMyDeviceLock);
 
+  //
+  // The BAR1 of this PCI device is used for shared memory and is supposed to
+  // look like MMIO. The address space of the BAR1 will be used to map the
+  // Grant Table.
+  //
+  Status = PciIo->GetBarAttributes (PciIo, PCI_BAR_IDX1, NULL, (VOID**) &BarDesc);
+  ASSERT_EFI_ERROR (Status);
+  ASSERT (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM);
+
+  /* Get a Memory address for mapping the Grant Table. */
+  DEBUG ((EFI_D_INFO, "XenBus: BAR at %LX\n", BarDesc->AddrRangeMin));
+  MmioAddr = BarDesc->AddrRangeMin;
+  FreePool (BarDesc);
+
   Status = XenHyperpageInit (Dev);
   if (EFI_ERROR (Status)) {
     DEBUG ((EFI_D_ERROR, "XenBus: Unable to retrieve the hyperpage.\n"));
@@ -343,6 +360,8 @@ XenBusDxeDriverBindingStart (
     goto ErrorAllocated;
   }
 
+  XenGrantTableInit (Dev, MmioAddr);
+
   Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
                              NotifyExitBoot,
                              (VOID*) Dev,
@@ -396,6 +415,7 @@ XenBusDxeDriverBindingStop (
   XENBUS_DEVICE *Dev = mMyDevice;
 
   gBS->CloseEvent (Dev->ExitBootEvent);
+  XenGrantTableDeinit (Dev);
 
   gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
          This->DriverBindingHandle, ControllerHandle);
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index 444118a..b3421c2 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -35,6 +35,8 @@
   XenHypercall.h
   InterlockedCompareExchange16.c
   InterlockedCompareExchange16.h
+  GrantTable.c
+  GrantTable.h
 
 [Sources.IA32]
   Ia32/hypercall.S
-- 
Anthony PERARD

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

* [PATCH v3 10/19] OvmfPkg/XenBusDxe: Add Event Channel Notify.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (8 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 09/19] OvmfPkg/XenBusDxe: Add Grant Table functions Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 11/19] OvmfPkg/XenBusDxe: Add TestAndClearBit Anthony PERARD
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This first function is used to notify the other side that there is
something to do. The other side is another Xen domain.

License: This patch adds event_channel.h which is under MIT licence.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- Return error code from hypercall instead of ASSERT for
  XenEventChannelNotify
- moving event_channel.h to this patch.

Change in V2:
- file header
- coding style
- adding comment to functions
- Licenses
---
 .../Include/IndustryStandard/Xen/event_channel.h   | 118 +++++++++++++++++++++
 OvmfPkg/XenBusDxe/EventChannel.c                   |  49 +++++++++
 OvmfPkg/XenBusDxe/EventChannel.h                   |  52 +++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.inf                    |   2 +
 4 files changed, 221 insertions(+)
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/event_channel.h
 create mode 100644 OvmfPkg/XenBusDxe/EventChannel.c
 create mode 100644 OvmfPkg/XenBusDxe/EventChannel.h

diff --git a/OvmfPkg/Include/IndustryStandard/Xen/event_channel.h b/OvmfPkg/Include/IndustryStandard/Xen/event_channel.h
new file mode 100644
index 0000000..a09ed8d
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/event_channel.h
@@ -0,0 +1,118 @@
+/******************************************************************************
+ * event_channel.h
+ *
+ * Event channels between domains.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2003-2004, K A Fraser.
+ */
+
+#ifndef __XEN_PUBLIC_EVENT_CHANNEL_H__
+#define __XEN_PUBLIC_EVENT_CHANNEL_H__
+
+#include "xen.h"
+
+/*
+ * `incontents 150 evtchn Event Channels
+ *
+ * Event channels are the basic primitive provided by Xen for event
+ * notifications. An event is the Xen equivalent of a hardware
+ * interrupt. They essentially store one bit of information, the event
+ * of interest is signalled by transitioning this bit from 0 to 1.
+ *
+ * Notifications are received by a guest via an upcall from Xen,
+ * indicating when an event arrives (setting the bit). Further
+ * notifications are masked until the bit is cleared again (therefore,
+ * guests must check the value of the bit after re-enabling event
+ * delivery to ensure no missed notifications).
+ *
+ * Event notifications can be masked by setting a flag; this is
+ * equivalent to disabling interrupts and can be used to ensure
+ * atomicity of certain operations in the guest kernel.
+ *
+ * Event channels are represented by the evtchn_* fields in
+ * struct shared_info and struct vcpu_info.
+ */
+
+/*
+ * ` enum neg_errnoval
+ * ` HYPERVISOR_event_channel_op(enum event_channel_op cmd, VOID *args)
+ * `
+ * @cmd  == EVTCHNOP_* (event-channel operation).
+ * @args == struct evtchn_* Operation-specific extra arguments (NULL if none).
+ */
+
+/* ` enum event_channel_op { // EVTCHNOP_* => struct evtchn_* */
+#define EVTCHNOP_close            3
+#define EVTCHNOP_send             4
+#define EVTCHNOP_alloc_unbound    6
+/* ` } */
+
+typedef UINT32 evtchn_port_t;
+DEFINE_XEN_GUEST_HANDLE(evtchn_port_t);
+
+/*
+ * EVTCHNOP_alloc_unbound: Allocate a port in domain <dom> and mark as
+ * accepting interdomain bindings from domain <remote_dom>. A fresh port
+ * is allocated in <dom> and returned as <port>.
+ * NOTES:
+ *  1. If the caller is unprivileged then <dom> must be DOMID_SELF.
+ *  2. <rdom> may be DOMID_SELF, allowing loopback connections.
+ */
+struct evtchn_alloc_unbound {
+    /* IN parameters */
+    domid_t dom, remote_dom;
+    /* OUT parameters */
+    evtchn_port_t port;
+};
+typedef struct evtchn_alloc_unbound evtchn_alloc_unbound_t;
+
+/*
+ * EVTCHNOP_close: Close a local event channel <port>. If the channel is
+ * interdomain then the remote end is placed in the unbound state
+ * (EVTCHNSTAT_unbound), awaiting a new connection.
+ */
+struct evtchn_close {
+    /* IN parameters. */
+    evtchn_port_t port;
+};
+typedef struct evtchn_close evtchn_close_t;
+
+/*
+ * EVTCHNOP_send: Send an event to the remote end of the channel whose local
+ * endpoint is <port>.
+ */
+struct evtchn_send {
+    /* IN parameters. */
+    evtchn_port_t port;
+};
+typedef struct evtchn_send evtchn_send_t;
+
+#endif /* __XEN_PUBLIC_EVENT_CHANNEL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/XenBusDxe/EventChannel.c b/OvmfPkg/XenBusDxe/EventChannel.c
new file mode 100644
index 0000000..53d43db
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/EventChannel.c
@@ -0,0 +1,49 @@
+/** @file
+  Event Channel function implementation.
+
+  Event channel are use to notify of an event that happend in a shared
+  structure for example.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#include "EventChannel.h"
+#include "XenHypercall.h"
+
+UINT32
+XenEventChannelNotify (
+  IN XENBUS_DEVICE *Dev,
+  IN evtchn_port_t Port
+  )
+{
+  INTN ReturnCode;
+  evtchn_send_t Send;
+
+  Send.port = Port;
+  ReturnCode = XenHypercallEventChannelOp (Dev, EVTCHNOP_send, &Send);
+  return ReturnCode;
+}
diff --git a/OvmfPkg/XenBusDxe/EventChannel.h b/OvmfPkg/XenBusDxe/EventChannel.h
new file mode 100644
index 0000000..5cbe43b
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/EventChannel.h
@@ -0,0 +1,52 @@
+/** @file
+  Event Channel function declaration.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+#ifndef __XENBUS_EVENT_CHANNEL_H
+#define __XENBUS_EVENT_CHANNEL_H
+
+#include "XenBusDxe.h"
+
+#include <IndustryStandard/Xen/event_channel.h>
+
+/**
+  Send an event to the remote end of the channel whose local endpoint is Port.
+
+  @param Dev    A pointer to XENBUS_DEVICE.
+  @param Port   The port to notify.
+
+  @return       Return 0 on success, or return the errno code from the hypercall.
+**/
+UINT32
+XenEventChannelNotify (
+  IN XENBUS_DEVICE *Dev,
+  IN evtchn_port_t Port
+  );
+
+#endif
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index b3421c2..bfa083e 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -37,6 +37,8 @@
   InterlockedCompareExchange16.h
   GrantTable.c
   GrantTable.h
+  EventChannel.c
+  EventChannel.h
 
 [Sources.IA32]
   Ia32/hypercall.S
-- 
Anthony PERARD

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

* [PATCH v3 11/19] OvmfPkg/XenBusDxe: Add TestAndClearBit.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (9 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 10/19] OvmfPkg/XenBusDxe: Add Event Channel Notify Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 12/19] OvmfPkg/XenBusDxe: Add XenStore client implementation Anthony PERARD
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This atomically test's and clear's a bit.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Change in V3:
- adding IA32 support. (not yet reviewed)
  both XenBusDxe/Ia32/TestAndClearBit.{S,asm} are new

Change in V2:
- Adding .asm version
- Comment the function
---
 OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.S   | 13 +++++++++++++
 OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.asm | 17 +++++++++++++++++
 OvmfPkg/XenBusDxe/X64/TestAndClearBit.S    | 12 ++++++++++++
 OvmfPkg/XenBusDxe/X64/TestAndClearBit.asm  | 16 ++++++++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.h              | 19 +++++++++++++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.inf            |  4 ++++
 6 files changed, 81 insertions(+)
 create mode 100644 OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.S
 create mode 100644 OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.asm
 create mode 100644 OvmfPkg/XenBusDxe/X64/TestAndClearBit.S
 create mode 100644 OvmfPkg/XenBusDxe/X64/TestAndClearBit.asm

diff --git a/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.S b/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.S
new file mode 100644
index 0000000..abb9322
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.S
@@ -0,0 +1,13 @@
+# INT32
+# EFIAPI
+# TestAndClearBit (
+#   IN  INT32 Bit,
+#   IN  volatile VOID* Address
+#   );
+ASM_GLOBAL ASM_PFX(TestAndClearBit)
+ASM_PFX(TestAndClearBit):
+  mov 4(%esp), %ecx
+  mov 8(%esp), %edx
+  lock btrl %ecx, (%edx)
+  sbbl %eax, %eax
+  ret
diff --git a/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.asm b/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.asm
new file mode 100644
index 0000000..0fb3fa2
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/Ia32/TestAndClearBit.asm
@@ -0,0 +1,17 @@
+.code
+
+; INT32
+; EFIAPI
+; TestAndClearBit (
+;   IN  INT32 Bit,
+;   IN  volatile VOID* Address
+;   );
+TestAndClearBit PROC
+  mov ecx, [esp + 4]
+  mov edx, [esp + 8]
+  lock btr [edx], ecx
+  sbb eax, eax
+  ret
+TestAndClearBit ENDP
+
+END
diff --git a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.S b/OvmfPkg/XenBusDxe/X64/TestAndClearBit.S
new file mode 100644
index 0000000..ddc6feb
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/X64/TestAndClearBit.S
@@ -0,0 +1,12 @@
+# INT32
+# EFIAPI
+# TestAndClearBit (
+#   IN  INT32 Bit,                // rcx
+#   IN  volatile VOID* Address    // rdx
+#   );
+ASM_GLOBAL ASM_PFX(TestAndClearBit)
+ASM_PFX(TestAndClearBit):
+  lock
+  btrl %ecx, (%rdx)
+  sbbl %eax, %eax
+  ret
diff --git a/OvmfPkg/XenBusDxe/X64/TestAndClearBit.asm b/OvmfPkg/XenBusDxe/X64/TestAndClearBit.asm
new file mode 100644
index 0000000..c7fc83d
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/X64/TestAndClearBit.asm
@@ -0,0 +1,16 @@
+.code
+
+; INT32
+; EFIAPI
+; TestAndClearBit (
+;   IN  INT32 Bit,                // rcx
+;   IN  volatile VOID* Address    // rdx
+;   );
+TestAndClearBit PROC
+  lock
+  btr [rdx], ecx
+  sbb eax, eax
+  ret
+TestAndClearBit ENDP
+
+END
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index d286c35..4a0f402 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -113,4 +113,23 @@ struct _XENBUS_DEVICE {
   shared_info_t                 *SharedInfo;
 };
 
+/*
+ * Helpers
+ */
+
+/**
+  Atomically test and clear a bit.
+
+  @param Bit      Bit index to test in *Address
+  @param Address  The Address to the buffer that contain the bit to test.
+
+  @return Value of the Bit before it was cleared.
+**/
+INT32
+EFIAPI
+TestAndClearBit (
+  IN INT32 Bit,
+  IN volatile VOID *Address
+  );
+
 #endif
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index bfa083e..f2b474d 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -45,12 +45,16 @@
   Ia32/hypercall.asm
   Ia32/InterlockedCompareExchange16.S
   Ia32/InterlockedCompareExchange16.asm
+  Ia32/TestAndClearBit.S
+  Ia32/TestAndClearBit.asm
 
 [Sources.X64]
   X64/hypercall.S
   X64/hypercall.asm
   X64/InterlockedCompareExchange16.S
   X64/InterlockedCompareExchange16.asm
+  X64/TestAndClearBit.S
+  X64/TestAndClearBit.asm
 
 [LibraryClasses]
   UefiDriverEntryPoint
-- 
Anthony PERARD

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

* [PATCH v3 12/19] OvmfPkg/XenBusDxe: Add XenStore client implementation
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (10 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 11/19] OvmfPkg/XenBusDxe: Add TestAndClearBit Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 13/19] OvmfPkg/XenBusDxe: Add an helper AsciiStrDup Anthony PERARD
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

XenStore is a key/value database, which is running on another virtual
machine. It can be accessed through shared memory. This is a client
implementation.

Origin: FreeBSD 10.0

License: This patch adds several files under the MIT licence.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Change in V3:
- moving xs_wire.h from patch #1 to this patch
- fix return value of XenStoreListDirectory
- Use a timeout to print a debug message if the other side of the
  xenstore ring does not notify through the event channel.
  This is done with the new XenStoreWaitForEvent function.
- Have XenStoreReadReply check status of XenStoreProcessMessage and
  return an error if needed.
- Have XenStoreTalkv return the status of XenStoreReadReply.
- Have a loop to check for the quiescent of the response ring in the
  XenStoreInitComms function. (with a timeout of 5 seconds)
- use the recently introduced XenStore 'closing' feature.

Change in V2:
- Change comment style, from freebsd to ovmf
- Fix type of EventChannel
- Fix debug print, no more cast
- Implement XenStoreDeinit.
- Clean up comments
- Fix few codding style issue
- Add FAIL xenstore status value.
---
 OvmfPkg/Include/IndustryStandard/Xen/io/xs_wire.h |  149 +++
 OvmfPkg/Include/Protocol/XenBus.h                 |   29 +
 OvmfPkg/XenBusDxe/XenBusDxe.c                     |    5 +
 OvmfPkg/XenBusDxe/XenBusDxe.inf                   |    2 +
 OvmfPkg/XenBusDxe/XenStore.c                      | 1386 +++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenStore.h                      |  292 +++++
 6 files changed, 1863 insertions(+)
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/xs_wire.h
 create mode 100644 OvmfPkg/XenBusDxe/XenStore.c
 create mode 100644 OvmfPkg/XenBusDxe/XenStore.h

diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/xs_wire.h b/OvmfPkg/Include/IndustryStandard/Xen/io/xs_wire.h
new file mode 100644
index 0000000..9094431
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/io/xs_wire.h
@@ -0,0 +1,149 @@
+/*
+ * Details of the "wire" protocol between Xen Store Daemon and client
+ * library or guest kernel.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (C) 2005 Rusty Russell IBM Corporation
+ */
+
+#ifndef _XS_WIRE_H
+#define _XS_WIRE_H
+
+enum xsd_sockmsg_type
+{
+    XS_DEBUG,
+    XS_DIRECTORY,
+    XS_READ,
+    XS_GET_PERMS,
+    XS_WATCH,
+    XS_UNWATCH,
+    XS_TRANSACTION_START,
+    XS_TRANSACTION_END,
+    XS_INTRODUCE,
+    XS_RELEASE,
+    XS_GET_DOMAIN_PATH,
+    XS_WRITE,
+    XS_MKDIR,
+    XS_RM,
+    XS_SET_PERMS,
+    XS_WATCH_EVENT,
+    XS_ERROR,
+    XS_IS_DOMAIN_INTRODUCED,
+    XS_RESUME,
+    XS_SET_TARGET,
+    XS_RESTRICT,
+    XS_RESET_WATCHES,
+
+    XS_INVALID = 0xffff /* Guaranteed to remain an invalid type */
+};
+
+#define XS_WRITE_NONE "NONE"
+#define XS_WRITE_CREATE "CREATE"
+#define XS_WRITE_CREATE_EXCL "CREATE|EXCL"
+
+/* We hand errors as strings, for portability. */
+struct xsd_errors
+{
+    INT32 errnum;
+    const CHAR8 *errstring;
+};
+#ifdef EINVAL
+#define XSD_ERROR(x) { x, #x }
+/* LINTED: static unused */
+static struct xsd_errors xsd_errors[]
+#if defined(__GNUC__)
+__attribute__((unused))
+#endif
+    = {
+    XSD_ERROR(EINVAL),
+    XSD_ERROR(EACCES),
+    XSD_ERROR(EEXIST),
+    XSD_ERROR(EISDIR),
+    XSD_ERROR(ENOENT),
+    XSD_ERROR(ENOMEM),
+    XSD_ERROR(ENOSPC),
+    XSD_ERROR(EIO),
+    XSD_ERROR(ENOTEMPTY),
+    XSD_ERROR(ENOSYS),
+    XSD_ERROR(EROFS),
+    XSD_ERROR(EBUSY),
+    XSD_ERROR(EAGAIN),
+    XSD_ERROR(EISCONN),
+    XSD_ERROR(E2BIG)
+};
+#endif
+
+struct xsd_sockmsg
+{
+    UINT32 type;  /* XS_??? */
+    UINT32 req_id;/* Request identifier, echoed in daemon's response.  */
+    UINT32 tx_id; /* Transaction id (0 if not related to a transaction). */
+    UINT32 len;   /* Length of data following this. */
+
+    /* Generally followed by nul-terminated string(s). */
+};
+
+enum xs_watch_type
+{
+    XS_WATCH_PATH = 0,
+    XS_WATCH_TOKEN
+};
+
+/*
+ * `incontents 150 xenstore_struct XenStore wire protocol.
+ *
+ * Inter-domain shared memory communications. */
+#define XENSTORE_RING_SIZE 1024
+typedef UINT32 XENSTORE_RING_IDX;
+#define MASK_XENSTORE_IDX(idx) ((idx) & (XENSTORE_RING_SIZE-1))
+struct xenstore_domain_interface {
+    CHAR8 req[XENSTORE_RING_SIZE]; /* Requests to xenstore daemon. */
+    CHAR8 rsp[XENSTORE_RING_SIZE]; /* Replies and async watch events. */
+    XENSTORE_RING_IDX req_cons, req_prod;
+    XENSTORE_RING_IDX rsp_cons, rsp_prod;
+    UINT32 server_features; /* Bitmap of features supported by the server */
+    UINT32 connection;
+};
+
+/* Violating this is very bad.  See docs/misc/xenstore.txt. */
+#define XENSTORE_PAYLOAD_MAX 4096
+
+/* Violating these just gets you an error back */
+#define XENSTORE_ABS_PATH_MAX 3072
+#define XENSTORE_REL_PATH_MAX 2048
+
+/* The ability to reconnect a ring */
+#define XENSTORE_SERVER_FEATURE_RECONNECTION 1
+
+/* Valid values for the connection field */
+#define XENSTORE_CONNECTED 0 /* the steady-state */
+#define XENSTORE_RECONNECT 1 /* guest has initiated a reconnect */
+
+#endif /* _XS_WIRE_H */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h
index 03d23bf..2c28a97 100644
--- a/OvmfPkg/Include/Protocol/XenBus.h
+++ b/OvmfPkg/Include/Protocol/XenBus.h
@@ -48,6 +48,35 @@
 ///
 typedef struct _XENBUS_PROTOCOL XENBUS_PROTOCOL;
 
+typedef enum xenbus_state XenBusState;
+
+typedef struct
+{
+  UINT32 Id;
+} XENSTORE_TRANSACTION;
+
+#define XST_NIL ((XENSTORE_TRANSACTION) { 0 })
+
+typedef enum {
+  XENSTORE_STATUS_SUCCESS = 0,
+  XENSTORE_STATUS_FAIL,
+  XENSTORE_STATUS_EINVAL,
+  XENSTORE_STATUS_EACCES,
+  XENSTORE_STATUS_EEXIST,
+  XENSTORE_STATUS_EISDIR,
+  XENSTORE_STATUS_ENOENT,
+  XENSTORE_STATUS_ENOMEM,
+  XENSTORE_STATUS_ENOSPC,
+  XENSTORE_STATUS_EIO,
+  XENSTORE_STATUS_ENOTEMPTY,
+  XENSTORE_STATUS_ENOSYS,
+  XENSTORE_STATUS_EROFS,
+  XENSTORE_STATUS_EBUSY,
+  XENSTORE_STATUS_EAGAIN,
+  XENSTORE_STATUS_EISCONN,
+  XENSTORE_STATUS_E2BIG
+} XENSTORE_STATUS;
+
 
 #include <IndustryStandard/Xen/grant_table.h>
 
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index fa267b6..69e1609 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -47,6 +47,7 @@
 
 #include "XenHypercall.h"
 #include "GrantTable.h"
+#include "XenStore.h"
 
 
 ///
@@ -362,6 +363,9 @@ XenBusDxeDriverBindingStart (
 
   XenGrantTableInit (Dev, MmioAddr);
 
+  Status = XenStoreInit (Dev);
+  ASSERT_EFI_ERROR (Status);
+
   Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
                              NotifyExitBoot,
                              (VOID*) Dev,
@@ -415,6 +419,7 @@ XenBusDxeDriverBindingStop (
   XENBUS_DEVICE *Dev = mMyDevice;
 
   gBS->CloseEvent (Dev->ExitBootEvent);
+  XenStoreDeinit (Dev);
   XenGrantTableDeinit (Dev);
 
   gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index f2b474d..8e2466e 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -39,6 +39,8 @@
   GrantTable.h
   EventChannel.c
   EventChannel.h
+  XenStore.c
+  XenStore.h
 
 [Sources.IA32]
   Ia32/hypercall.S
diff --git a/OvmfPkg/XenBusDxe/XenStore.c b/OvmfPkg/XenBusDxe/XenStore.c
new file mode 100644
index 0000000..8ba4328
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenStore.c
@@ -0,0 +1,1386 @@
+/** @file
+  Low-level kernel interface to the XenStore.
+
+  The XenStore interface is a simple storage system that is a means of
+  communicating state and configuration data between the Xen Domain 0
+  and the various guest domains.  All configuration data other than
+  a small amount of essential information required during the early
+  boot process of launching a Xen aware guest, is managed using the
+  XenStore.
+
+  The XenStore is ASCII string based, and has a structure and semantics
+  similar to a filesystem.  There are files and directories, the directories
+  able to contain files or other directories.  The depth of the hierachy
+  is only limited by the XenStore's maximum path length.
+
+  The communication channel between the XenStore service and other
+  domains is via two, guest specific, ring buffers in a shared memory
+  area.  One ring buffer is used for communicating in each direction.
+  The grant table references for this shared memory are given to the
+  guest either via the xen_start_info structure for a fully para-
+  virtualized guest, or via HVM hypercalls for a hardware virtualized
+  guest.
+
+  The XenStore communication relies on an event channel and thus
+  interrupts.  But under OVMF this XenStore client will pull the
+  state of the event channel.
+
+  Several Xen services depend on the XenStore, most notably the
+  XenBus used to discover and manage Xen devices.
+
+  Copyright (C) 2005 Rusty Russell, IBM Corporation
+  Copyright (C) 2009,2010 Spectra Logic Corporation
+  Copyright (C) 2014, Citrix Ltd.
+
+  This file may be distributed separately from the Linux kernel, or
+  incorporated into other software packages, subject to the following license:
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this source file (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use, copy, modify,
+  merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  IN THE SOFTWARE.
+**/
+
+#include "XenStore.h"
+
+#include <Library/PrintLib.h>
+
+#include <IndustryStandard/Xen/hvm/params.h>
+
+#include "XenHypercall.h"
+#include "EventChannel.h"
+
+//
+// Private Data Structures
+//
+
+typedef struct {
+  CONST VOID  *Data;
+  UINTN       Len;
+} WRITE_REQUEST;
+
+/* Register callback to watch subtree (node) in the XenStore. */
+#define XENSTORE_WATCH_SIGNATURE SIGNATURE_32 ('X','S','w','a')
+struct _XENSTORE_WATCH
+{
+  UINT32      Signature;
+  LIST_ENTRY  Link;
+
+  /* Path being watched. */
+  CHAR8       *Node;
+};
+
+#define XENSTORE_WATCH_FROM_LINK(l) \
+  CR (l, XENSTORE_WATCH, Link, XENSTORE_WATCH_SIGNATURE)
+
+
+/**
+ * Structure capturing messages received from the XenStore service.
+ */
+#define XENSTORE_MESSAGE_SIGNATURE SIGNATURE_32 ('X', 'S', 's', 'm')
+typedef struct {
+  UINT32 Signature;
+  LIST_ENTRY Link;
+
+  struct xsd_sockmsg Header;
+
+  union {
+    /* Queued replies. */
+    struct {
+      CHAR8 *Body;
+    } Reply;
+
+    /* Queued watch events. */
+    struct {
+      XENSTORE_WATCH *Handle;
+      CONST CHAR8 **Vector;
+      UINT32 VectorSize;
+    } Watch;
+  } u;
+} XENSTORE_MESSAGE;
+#define XENSTORE_MESSAGE_FROM_LINK(r) \
+  CR (r, XENSTORE_MESSAGE, Link, XENSTORE_MESSAGE_SIGNATURE)
+
+/**
+ * Container for all XenStore related state.
+ */
+typedef struct {
+  /**
+   * Pointer to shared memory communication structures allowing us
+   * to communicate with the XenStore service.
+   */
+  struct xenstore_domain_interface *XenStore;
+
+  XENBUS_DEVICE *Dev;
+
+  /**
+   * A list of replies to our requests.
+   *
+   * The reply list is filled by xs_rcv_thread().  It
+   * is consumed by the context that issued the request
+   * to which a reply is made.  The requester blocks in
+   * XenStoreReadReply ().
+   *
+   * /note Only one requesting context can be active at a time.
+   */
+  LIST_ENTRY ReplyList;
+
+  /** Lock protecting the reply list. */
+  EFI_LOCK ReplyLock;
+
+  /**
+   * List of registered watches.
+   */
+  LIST_ENTRY RegisteredWatches;
+
+  /** Lock protecting the registered watches list. */
+  EFI_LOCK RegisteredWatchesLock;
+
+  /**
+   * List of pending watch callback events.
+   */
+  LIST_ENTRY WatchEvents;
+
+  /** Lock protecting the watch calback list. */
+  EFI_LOCK WatchEventsLock;
+
+  /**
+   * The event channel for communicating with the
+   * XenStore service.
+   */
+  evtchn_port_t EventChannel;
+
+  /** Handle for XenStore events. */
+  EFI_EVENT EventChannelEvent;
+} XENSTORE_PRIVATE;
+
+//
+// Global Data
+//
+static XENSTORE_PRIVATE xs;
+
+
+//
+// Private Utility Functions
+//
+
+/**
+  Count and optionally record pointers to a number of NUL terminated
+  strings in a buffer.
+
+  @param Strings  A pointer to a contiguous buffer of NUL terminated strings.
+  @param Len      The length of the buffer pointed to by strings.
+  @param Dst      An array to store pointers to each string found in strings.
+
+  @return  A count of the number of strings found.
+**/
+STATIC
+UINT32
+ExtractStrings (
+  IN  CONST CHAR8 *Strings,
+  IN  UINTN       Len,
+  OUT CONST CHAR8 **Dst OPTIONAL
+  )
+{
+  UINT32 Num = 0;
+  CONST CHAR8 *Ptr;
+
+  for (Ptr = Strings; Ptr < Strings + Len; Ptr += AsciiStrSize (Ptr)) {
+    if (Dst != NULL) {
+      *Dst++ = Ptr;
+    }
+    Num++;
+  }
+
+  return Num;
+}
+
+/**
+  Convert a contiguous buffer containing a series of NUL terminated
+  strings into an array of pointers to strings.
+
+  The returned pointer references the array of string pointers which
+  is followed by the storage for the string data.  It is the client's
+  responsibility to free this storage.
+
+  The storage addressed by Strings is free'd prior to Split returning.
+
+  @param Strings  A pointer to a contiguous buffer of NUL terminated strings.
+  @param Len      The length of the buffer pointed to by strings.
+  @param NumPtr   The number of strings found and returned in the strings
+                  array.
+
+  @return  An array of pointers to the strings found in the input buffer.
+**/
+STATIC
+CONST CHAR8 **
+Split (
+  IN  CHAR8   *Strings,
+  IN  UINTN   Len,
+  OUT UINT32  *NumPtr
+  )
+{
+  CONST CHAR8 **Dst;
+
+  ASSERT(NumPtr != NULL);
+  ASSERT(Strings != NULL);
+
+  /* Protect against unterminated buffers. */
+  if (Len > 0) {
+    Strings[Len - 1] = '\0';
+  }
+
+  /* Count the Strings. */
+  *NumPtr = ExtractStrings (Strings, Len, NULL);
+
+  /* Transfer to one big alloc for easy freeing by the caller. */
+  Dst = AllocatePool (*NumPtr * sizeof (CHAR8 *) + Len);
+  CopyMem (&Dst[*NumPtr], Strings, Len);
+  FreePool (Strings);
+
+  /* Extract pointers to newly allocated array. */
+  Strings = (CHAR8 *) &Dst[*NumPtr];
+  ExtractStrings (Strings, Len, Dst);
+
+  return (Dst);
+}
+
+/**
+  Convert from watch token (unique identifier) to the associated
+  internal tracking structure for this watch.
+
+  @param Tocken  The unique identifier for the watch to find.
+
+  @return  A pointer to the found watch structure or NULL.
+**/
+STATIC
+XENSTORE_WATCH *
+XenStoreFindWatch (
+  IN CONST CHAR8 *Token
+  )
+{
+  XENSTORE_WATCH *Watch, *WantedWatch;
+  LIST_ENTRY *Entry;
+
+  WantedWatch = (VOID *) AsciiStrHexToUintn (Token);
+
+  if (IsListEmpty (&xs.RegisteredWatches)) {
+    return NULL;
+  }
+  for (Entry = GetFirstNode (&xs.RegisteredWatches);
+       !IsNull (&xs.RegisteredWatches, Entry);
+       Entry = GetNextNode (&xs.RegisteredWatches, Entry)) {
+    Watch = XENSTORE_WATCH_FROM_LINK (Entry);
+    if (Watch == WantedWatch)
+      return Watch;
+  }
+
+  return NULL;
+}
+
+//
+// Public Utility Functions
+// API comments for these methods can be found in XenStore.h
+//
+
+CHAR8 *
+XenStoreJoin (
+  IN CONST CHAR8 *DirectoryPath,
+  IN CONST CHAR8 *Node
+  )
+{
+  CHAR8 *Buf;
+
+  /* +1 for '/' and +1 for '\0' */
+  Buf = AllocateZeroPool (
+          AsciiStrLen (DirectoryPath) + AsciiStrLen (Node) + 2);
+  AsciiStrCat (Buf, DirectoryPath);
+  if (Node[0] != '\0') {
+    AsciiStrCat (Buf, "/");
+    AsciiStrCat (Buf, Node);
+  }
+
+  return Buf;
+}
+
+//
+// Low Level Communication Management
+//
+
+/**
+  Verify that the indexes for a ring are valid.
+
+  The difference between the producer and consumer cannot
+  exceed the size of the ring.
+
+  @param Cons  The consumer index for the ring to test.
+  @param Prod  The producer index for the ring to test.
+
+  @retval TRUE   If indexes are in range.
+  @retval FALSE  If the indexes are out of range.
+**/
+STATIC
+BOOLEAN
+XenStoreCheckIndexes (
+  XENSTORE_RING_IDX Cons,
+  XENSTORE_RING_IDX Prod
+  )
+{
+  return ((Prod - Cons) <= XENSTORE_RING_SIZE);
+}
+
+/**
+  Return a pointer to, and the length of, the contiguous
+  free region available for output in a ring buffer.
+
+  @param Cons    The consumer index for the ring.
+  @param Prod    The producer index for the ring.
+  @param Buffer  The base address of the ring's storage.
+  @param LenPtr  The amount of contiguous storage available.
+
+  @return  A pointer to the start location of the free region.
+**/
+STATIC
+VOID *
+XenStoreGetOutputChunk (
+  IN  XENSTORE_RING_IDX Cons,
+  IN  XENSTORE_RING_IDX Prod,
+  IN  CHAR8             *Buffer,
+  OUT UINT32            *LenPtr
+  )
+{
+  UINT32 Len;
+  Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Prod);
+  if ((XENSTORE_RING_SIZE - (Prod - Cons)) < Len) {
+    Len = XENSTORE_RING_SIZE - (Prod - Cons);
+  }
+  *LenPtr = Len;
+  return (Buffer + MASK_XENSTORE_IDX (Prod));
+}
+
+/**
+  Return a pointer to, and the length of, the contiguous
+  data available to read from a ring buffer.
+
+  @param Cons    The consumer index for the ring.
+  @param Prod    The producer index for the ring.
+  @param Buffer  The base address of the ring's storage.
+  @param LenPtr  The amount of contiguous data available to read.
+
+  @return  A pointer to the start location of the available data.
+**/
+STATIC
+CONST VOID *
+XenStoreGetInputChunk (
+  IN  XENSTORE_RING_IDX Cons,
+  IN  XENSTORE_RING_IDX Prod,
+  IN  CONST CHAR8       *Buffer,
+  OUT UINT32            *LenPtr
+  )
+{
+  UINT32 Len;
+
+  Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Cons);
+  if ((Prod - Cons) < Len) {
+    Len = Prod - Cons;
+  }
+  *LenPtr = Len;
+  return (Buffer + MASK_XENSTORE_IDX (Cons));
+}
+
+/**
+  Wait for an event or timeout.
+
+  @param Event    Event to wait for.
+  @param Timeout  A timeout value in 100ns units.
+
+  @retval EFI_SUCCESS   Event have been triggered or the current TPL is not
+                        TPL_APPLICATION.
+  @retval EFI_TIMEOUT   Timeout have expired.
+**/
+STATIC
+EFI_STATUS
+XenStoreWaitForEvent (
+  IN EFI_EVENT Event,
+  IN UINT64    Timeout
+  )
+{
+  UINTN Index;
+  EFI_STATUS Status;
+  EFI_EVENT TimerEvent;
+  EFI_EVENT WaitList[2];
+
+  gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+  gBS->SetTimer (TimerEvent, TimerRelative, Timeout);
+
+  WaitList[0] = xs.EventChannelEvent;
+  WaitList[1] = TimerEvent;
+  Status = gBS->WaitForEvent (2, WaitList, &Index);
+  ASSERT (Status != EFI_INVALID_PARAMETER);
+  gBS->CloseEvent (TimerEvent);
+  if (Status == EFI_UNSUPPORTED) {
+    return EFI_SUCCESS;
+  }
+  if (Index == 1) {
+    return EFI_TIMEOUT;
+  } else {
+    return EFI_SUCCESS;
+  }
+}
+
+/**
+  Transmit data to the XenStore service.
+
+  The buffer pointed to by DataPtr is at least Len bytes in length.
+
+  @param DataPtr  A pointer to the contiguous data to send.
+  @param Len      The amount of data to send.
+
+  @return  On success 0, otherwise an errno value indicating the
+           cause of failure.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreWriteStore (
+  IN CONST VOID *DataPtr,
+  IN UINTN      Len
+  )
+{
+  XENSTORE_RING_IDX Cons, Prod;
+  CONST CHAR8 *Data = (CONST CHAR8 *)DataPtr;
+
+  while (Len != 0) {
+    void *Dest;
+    UINT32 Available;
+
+    Cons = xs.XenStore->req_cons;
+    Prod = xs.XenStore->req_prod;
+    if ((Prod - Cons) == XENSTORE_RING_SIZE) {
+      /*
+       * Output ring is full. Wait for a ring event.
+       *
+       * Note that the events from both queues are combined, so being woken
+       * does not guarantee that data exist in the read ring.
+       */
+      EFI_STATUS Status;
+
+      Status = XenStoreWaitForEvent (xs.EventChannelEvent,
+                                     EFI_TIMER_PERIOD_SECONDS (1));
+      if (Status == EFI_TIMEOUT) {
+        DEBUG ((EFI_D_WARN, "XenStore Write, waiting for a ring event.\n"));
+      }
+      continue;
+    }
+
+    /* Verify queue sanity. */
+    if (!XenStoreCheckIndexes (Cons, Prod)) {
+      xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
+      return XENSTORE_STATUS_EIO;
+    }
+
+    Dest = XenStoreGetOutputChunk (Cons, Prod, xs.XenStore->req, &Available);
+    if (Available > Len) {
+      Available = Len;
+    }
+
+    CopyMem (Dest, Data, Available);
+    Data += Available;
+    Len -= Available;
+
+    /*
+     * The store to the producer index, which indicates
+     * to the other side that new data has arrived, must
+     * be visible only after our copy of the data into the
+     * ring has completed.
+     */
+    MemoryFence ();
+    xs.XenStore->req_prod += Available;
+
+    /*
+     * The other side will see the change to req_prod at the time of the
+     * interrupt.
+     */
+    MemoryFence ();
+    XenEventChannelNotify (xs.Dev, xs.EventChannel);
+  }
+
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+/**
+  Receive data from the XenStore service.
+
+  The buffer pointed to by DataPtr is at least Len bytes in length.
+
+  @param DataPtr  A pointer to the contiguous buffer to receive the data.
+  @param Len      The amount of data to receive.
+
+  @return  On success 0, otherwise an errno value indicating the
+           cause of failure.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreReadStore (
+  OUT VOID *DataPtr,
+  IN  UINTN Len
+  )
+{
+  XENSTORE_RING_IDX Cons, Prod;
+  CHAR8 *Data = (CHAR8 *) DataPtr;
+
+  while (Len != 0) {
+    UINT32 Available;
+    CONST CHAR8 *Src;
+
+    Cons = xs.XenStore->rsp_cons;
+    Prod = xs.XenStore->rsp_prod;
+    if (Cons == Prod) {
+      /*
+       * Nothing to read. Wait for a ring event.
+       *
+       * Note that the events from both queues are combined, so being woken
+       * does not guarantee that data exist in the read ring.
+       */
+      EFI_STATUS Status;
+
+      Status = XenStoreWaitForEvent (xs.EventChannelEvent,
+                                     EFI_TIMER_PERIOD_SECONDS (1));
+      if (Status == EFI_TIMEOUT) {
+        DEBUG ((EFI_D_WARN, "XenStore Read, waiting for a ring event.\n"));
+      }
+      continue;
+    }
+
+    /* Verify queue sanity. */
+    if (!XenStoreCheckIndexes (Cons, Prod)) {
+      xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
+      return XENSTORE_STATUS_EIO;
+    }
+
+    Src = XenStoreGetInputChunk (Cons, Prod, xs.XenStore->rsp, &Available);
+    if (Available > Len) {
+      Available = Len;
+    }
+
+    /*
+     * Insure the data we read is related to the indexes
+     * we read above.
+     */
+    MemoryFence ();
+
+    CopyMem (Data, Src, Available);
+    Data += Available;
+    Len -= Available;
+
+    /*
+     * Insure that the producer of this ring does not see
+     * the ring space as free until after we have copied it
+     * out.
+     */
+    MemoryFence ();
+    xs.XenStore->rsp_cons += Available;
+
+    /*
+     * The producer will see the updated consumer index when the event is
+     * delivered.
+     */
+    MemoryFence ();
+    XenEventChannelNotify (xs.Dev, xs.EventChannel);
+  }
+
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+//
+// Received Message Processing
+//
+
+/**
+  Block reading the next message from the XenStore service and
+  process the result.
+
+  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno value
+           indicating the type of failure encountered.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreProcessMessage (
+  VOID
+  )
+{
+  XENSTORE_MESSAGE *Message;
+  CHAR8 *Body;
+  XENSTORE_STATUS Status;
+
+  Message = AllocateZeroPool (sizeof (XENSTORE_MESSAGE));
+  Message->Signature = XENSTORE_MESSAGE_SIGNATURE;
+  Status = XenStoreReadStore (&Message->Header, sizeof (Message->Header));
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    FreePool (Message);
+    DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
+    return Status;
+  }
+
+  Body = AllocatePool (Message->Header.len + 1);
+  Status = XenStoreReadStore (Body, Message->Header.len);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    FreePool (Body);
+    FreePool (Message);
+    DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
+    return Status;
+  }
+  Body[Message->Header.len] = '\0';
+
+  if (Message->Header.type == XS_WATCH_EVENT) {
+    Message->u.Watch.Vector = Split(Body, Message->Header.len,
+                                    &Message->u.Watch.VectorSize);
+
+    EfiAcquireLock (&xs.RegisteredWatchesLock);
+    Message->u.Watch.Handle =
+      XenStoreFindWatch (Message->u.Watch.Vector[XS_WATCH_TOKEN]);
+    DEBUG ((EFI_D_INFO, "XenStore: Watch event %a\n",
+            Message->u.Watch.Vector[XS_WATCH_TOKEN]));
+    if (Message->u.Watch.Handle != NULL) {
+      EfiAcquireLock (&xs.WatchEventsLock);
+      InsertHeadList (&xs.WatchEvents, &Message->Link);
+      EfiReleaseLock (&xs.WatchEventsLock);
+    } else {
+      DEBUG ((EFI_D_WARN, "XenStore: Watch handle %a not found\n",
+              Message->u.Watch.Vector[XS_WATCH_TOKEN]));
+      FreePool(Message->u.Watch.Vector);
+      FreePool(Message);
+    }
+    EfiReleaseLock (&xs.RegisteredWatchesLock);
+  } else {
+    Message->u.Reply.Body = Body;
+    EfiAcquireLock (&xs.ReplyLock);
+    InsertTailList (&xs.ReplyList, &Message->Link);
+    EfiReleaseLock (&xs.ReplyLock);
+  }
+
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+//
+// XenStore Message Request/Reply Processing
+//
+
+/**
+  Convert a XenStore error string into an errno number.
+
+  Unknown error strings are converted to EINVAL.
+
+  @param errorstring  The error string to convert.
+
+  @return  The errno best matching the input string.
+
+**/
+typedef struct {
+  XENSTORE_STATUS Status;
+  CONST CHAR8 *ErrorStr;
+} XenStoreErrors;
+
+static XenStoreErrors gXenStoreErrors[] = {
+  { XENSTORE_STATUS_EINVAL, "EINVAL" },
+  { XENSTORE_STATUS_EACCES, "EACCES" },
+  { XENSTORE_STATUS_EEXIST, "EEXIST" },
+  { XENSTORE_STATUS_EISDIR, "EISDIR" },
+  { XENSTORE_STATUS_ENOENT, "ENOENT" },
+  { XENSTORE_STATUS_ENOMEM, "ENOMEM" },
+  { XENSTORE_STATUS_ENOSPC, "ENOSPC" },
+  { XENSTORE_STATUS_EIO, "EIO" },
+  { XENSTORE_STATUS_ENOTEMPTY, "ENOTEMPTY" },
+  { XENSTORE_STATUS_ENOSYS, "ENOSYS" },
+  { XENSTORE_STATUS_EROFS, "EROFS" },
+  { XENSTORE_STATUS_EBUSY, "EBUSY" },
+  { XENSTORE_STATUS_EAGAIN, "EAGAIN" },
+  { XENSTORE_STATUS_EISCONN, "EISCONN" },
+  { XENSTORE_STATUS_E2BIG, "E2BIG" }
+};
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+STATIC
+XENSTORE_STATUS
+XenStoreGetError (
+  CONST CHAR8 *ErrorStr
+  )
+{
+  UINT32 Index;
+
+  for (Index = 0; Index < ARRAY_SIZE(gXenStoreErrors); Index++) {
+    if (!AsciiStrCmp (ErrorStr, gXenStoreErrors[Index].ErrorStr)) {
+      return gXenStoreErrors[Index].Status;
+    }
+  }
+  DEBUG ((EFI_D_WARN, "XenStore gave unknown error %a\n", ErrorStr));
+  return XENSTORE_STATUS_EINVAL;
+}
+
+/**
+  Block waiting for a reply to a message request.
+
+  @param TypePtr The returned type of the reply.
+  @param LenPtr  The returned body length of the reply.
+  @param Result  The returned body of the reply.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreReadReply (
+  OUT enum xsd_sockmsg_type *TypePtr,
+  OUT UINT32 *LenPtr OPTIONAL,
+  OUT VOID **Result
+  )
+{
+  XENSTORE_MESSAGE *Message;
+  LIST_ENTRY *Entry;
+  CHAR8 *Body;
+
+  while (IsListEmpty (&xs.ReplyList)) {
+    XENSTORE_STATUS Status;
+    Status = XenStoreProcessMessage ();
+    if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) {
+      DEBUG ((EFI_D_ERROR, "XenStore, error while reading the ring (%d).",
+              Status));
+      return Status;
+    }
+  }
+  EfiAcquireLock (&xs.ReplyLock);
+  Entry = GetFirstNode (&xs.ReplyList);
+  Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
+  RemoveEntryList (Entry);
+  EfiReleaseLock (&xs.ReplyLock);
+
+  *TypePtr = Message->Header.type;
+  if (LenPtr != NULL) {
+    *LenPtr = Message->Header.len;
+  }
+  Body = Message->u.Reply.Body;
+
+  FreePool (Message);
+  *Result = Body;
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+/**
+  Send a message with an optionally muti-part body to the XenStore service.
+
+  @param Transaction    The transaction to use for this request.
+  @param RequestType    The type of message to send.
+  @param WriteRequest   Pointers to the body sections of the request.
+  @param NumRequests    The number of body sections in the request.
+  @param LenPtr         The returned length of the reply.
+  @param ResultPtr      The returned body of the reply.
+
+  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
+           the cause of failure.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreTalkv (
+  IN  XENSTORE_TRANSACTION    Transaction,
+  IN  enum xsd_sockmsg_type   RequestType,
+  IN  CONST WRITE_REQUEST     *WriteRequest,
+  IN  UINT32                  NumRequests,
+  OUT UINT32                  *LenPtr OPTIONAL,
+  OUT VOID                    **ResultPtr OPTIONAL
+  )
+{
+  struct xsd_sockmsg Message;
+  void *Return = NULL;
+  UINT32 Index;
+  XENSTORE_STATUS Status;
+
+  Message.tx_id = Transaction.Id;
+  Message.req_id = 0;
+  Message.type = RequestType;
+  Message.len = 0;
+  for (Index = 0; Index < NumRequests; Index++) {
+    Message.len += WriteRequest[Index].Len;
+  }
+
+  Status = XenStoreWriteStore (&Message, sizeof (Message));
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
+    goto Error;
+  }
+
+  for (Index = 0; Index < NumRequests; Index++) {
+    Status = XenStoreWriteStore (WriteRequest[Index].Data, WriteRequest[Index].Len);
+    if (Status != XENSTORE_STATUS_SUCCESS) {
+      DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
+      goto Error;
+    }
+  }
+
+  Status = XenStoreReadReply (&Message.type, LenPtr, &Return);
+
+Error:
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    return Status;
+  }
+
+  if (Message.type == XS_ERROR) {
+    Status = XenStoreGetError (Return);
+    FreePool (Return);
+    return Status;
+  }
+
+  /* Reply is either error or an echo of our request message type. */
+  ASSERT (Message.type == RequestType);
+
+  if (ResultPtr) {
+    *ResultPtr = Return;
+  } else {
+    FreePool (Return);
+  }
+
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+/**
+  Wrapper for XenStoreTalkv allowing easy transmission of a message with
+  a single, contiguous, message body.
+
+  The returned result is provided in malloced storage and thus must be free'd
+  by the caller.
+
+  @param Transaction    The transaction to use for this request.
+  @param RequestType    The type of message to send.
+  @param Body           The body of the request.
+  @param LenPtr         The returned length of the reply.
+  @param Result         The returned body of the reply.
+
+  @return  0 on success.  Otherwise an errno indicating
+           the cause of failure.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreSingle (
+  IN  XENSTORE_TRANSACTION    Transaction,
+  IN  enum xsd_sockmsg_type   RequestType,
+  IN  CONST CHAR8             *Body,
+  OUT UINT32                  *LenPtr OPTIONAL,
+  OUT VOID                    **Result OPTIONAL
+  )
+{
+  WRITE_REQUEST WriteRequest;
+
+  WriteRequest.Data = (VOID *) Body;
+  WriteRequest.Len = AsciiStrSize (Body);
+
+  return XenStoreTalkv (Transaction, RequestType, &WriteRequest, 1,
+                        LenPtr, Result);
+}
+
+//
+// XenStore Watch Support
+//
+
+/**
+  Transmit a watch request to the XenStore service.
+
+  @param Path    The path in the XenStore to watch.
+  @param Tocken  A unique identifier for this watch.
+
+  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating the
+           cause of failure.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreWatch (
+  CONST CHAR8 *Path,
+  CONST CHAR8 *Token
+  )
+{
+  WRITE_REQUEST WriteRequest[2];
+
+  WriteRequest[0].Data = (VOID *) Path;
+  WriteRequest[0].Len = AsciiStrSize (Path);
+  WriteRequest[1].Data = (VOID *) Token;
+  WriteRequest[1].Len = AsciiStrSize (Token);
+
+  return XenStoreTalkv (XST_NIL, XS_WATCH, WriteRequest, 2, NULL, NULL);
+}
+
+/**
+  Transmit an uwatch request to the XenStore service.
+
+  @param Path    The path in the XenStore to watch.
+  @param Tocken  A unique identifier for this watch.
+
+  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
+           the cause of failure.
+**/
+STATIC
+XENSTORE_STATUS
+XenStoreUnwatch (
+  CONST CHAR8 *Path,
+  CONST CHAR8 *Token
+  )
+{
+  WRITE_REQUEST WriteRequest[2];
+
+  WriteRequest[0].Data = (VOID *) Path;
+  WriteRequest[0].Len = AsciiStrSize (Path);
+  WriteRequest[1].Data = (VOID *) Token;
+  WriteRequest[1].Len = AsciiStrSize (Token);
+
+  return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL);
+}
+
+VOID
+EFIAPI
+NotifyEventChannelCheckForEvent (
+  IN EFI_EVENT Event,
+  IN VOID *Context
+  )
+{
+  XENSTORE_PRIVATE *xs;
+  xs = (XENSTORE_PRIVATE *)Context;
+  if (TestAndClearBit (xs->EventChannel, xs->Dev->SharedInfo->evtchn_pending)) {
+    gBS->SignalEvent (Event);
+  }
+}
+
+/**
+  Setup communication channels with the XenStore service.
+
+  @retval EFI_SUCCESS if everything went well.
+**/
+STATIC
+EFI_STATUS
+XenStoreInitComms (
+  XENSTORE_PRIVATE *xs
+  )
+{
+  EFI_STATUS Status;
+  EFI_EVENT TimerEvent;
+  struct xenstore_domain_interface *XenStore = xs->XenStore;
+
+  Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+  Status = gBS->SetTimer (TimerEvent, TimerRelative,
+                          EFI_TIMER_PERIOD_SECONDS (5));
+  while (XenStore->rsp_prod != XenStore->rsp_cons) {
+    Status = gBS->CheckEvent (TimerEvent);
+    if (!EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_WARN, "XENSTORE response ring is not quiescent "
+              "(%08x:%08x): fixing up\n",
+              XenStore->rsp_cons, XenStore->rsp_prod));
+      XenStore->rsp_cons = XenStore->rsp_prod;
+    }
+  }
+  gBS->CloseEvent (TimerEvent);
+
+  Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_NOTIFY,
+                             NotifyEventChannelCheckForEvent, xs,
+                             &xs->EventChannelEvent);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+/**
+  Initialize XenStore.
+
+  @param Dev  A XENBUS_DEVICE instance.
+
+  @retval EFI_SUCCESS if everything went well.
+**/
+EFI_STATUS
+XenStoreInit (
+  XENBUS_DEVICE *Dev
+  )
+{
+  EFI_STATUS Status;
+  /**
+   * The HVM guest pseudo-physical frame number.  This is Xen's mapping
+   * of the true machine frame number into our "physical address space".
+   */
+  UINTN XenStoreGpfn;
+
+  xs.Dev = Dev;
+
+  xs.EventChannel = XenHypercallHvmGetParam (Dev, HVM_PARAM_STORE_EVTCHN);
+  XenStoreGpfn = XenHypercallHvmGetParam (Dev, HVM_PARAM_STORE_PFN);
+  xs.XenStore = (VOID *) (XenStoreGpfn << EFI_PAGE_SHIFT);
+  DEBUG ((EFI_D_INFO, "XenBusInit: XenBus rings @%p, event channel %x\n",
+          xs.XenStore, xs.EventChannel));
+
+  InitializeListHead (&xs.ReplyList);
+  InitializeListHead (&xs.WatchEvents);
+  InitializeListHead (&xs.RegisteredWatches);
+
+  EfiInitializeLock (&xs.ReplyLock, TPL_NOTIFY);
+  EfiInitializeLock (&xs.RegisteredWatchesLock, TPL_NOTIFY);
+  EfiInitializeLock (&xs.WatchEventsLock, TPL_NOTIFY);
+
+  /* Initialize the shared memory rings to talk to xenstored */
+  Status = XenStoreInitComms (&xs);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return Status;
+}
+
+VOID
+XenStoreDeinit (
+  IN XENBUS_DEVICE *Dev
+  )
+{
+  //
+  // Emptying the list RegisteredWatches, but this list should already be
+  // empty. Every driver that is using Watches should unregister them when
+  // it is stopped.
+  //
+  if (!IsListEmpty (&xs.RegisteredWatches)) {
+    XENSTORE_WATCH *Watch;
+    LIST_ENTRY *Entry;
+    DEBUG ((EFI_D_WARN, "XenStore: RegisteredWatches is not empty, cleaning up..."));
+    Entry = GetFirstNode (&xs.RegisteredWatches);
+    while (!IsNull (&xs.RegisteredWatches, Entry)) {
+      Watch = XENSTORE_WATCH_FROM_LINK (Entry);
+      Entry = GetNextNode (&xs.RegisteredWatches, Entry);
+
+      XenStoreUnregisterWatch (Watch);
+    }
+  }
+
+  //
+  // Emptying the list WatchEvents, but this list should already be empty after
+  // having cleanup the list RegisteredWatches.
+  //
+  if (!IsListEmpty (&xs.WatchEvents)) {
+    LIST_ENTRY *Entry;
+    DEBUG ((EFI_D_WARN, "XenStore: WatchEvents is not empty, cleaning up..."));
+    Entry = GetFirstNode (&xs.WatchEvents);
+    while (!IsNull (&xs.WatchEvents, Entry)) {
+      XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
+      Entry = GetNextNode (&xs.WatchEvents, Entry);
+      RemoveEntryList (&Message->Link);
+      FreePool (Message->u.Watch.Vector);
+      FreePool (Message);
+    }
+  }
+
+  if (!IsListEmpty (&xs.ReplyList)) {
+    XENSTORE_MESSAGE *Message;
+    LIST_ENTRY *Entry;
+    Entry = GetFirstNode (&xs.ReplyList);
+    while (!IsNull (&xs.ReplyList, Entry)) {
+      Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
+      Entry = GetNextNode (&xs.ReplyList, Entry);
+      RemoveEntryList (&Message->Link);
+      FreePool (Message->u.Reply.Body);
+      FreePool (Message);
+    }
+  }
+
+  gBS->CloseEvent (xs.EventChannelEvent);
+
+  if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) {
+    xs.XenStore->connection = XENSTORE_RECONNECT;
+    XenEventChannelNotify (xs.Dev, xs.EventChannel);
+    while (*(volatile UINT32*)&xs.XenStore->connection == XENSTORE_RECONNECT) {
+      XenStoreWaitForEvent (xs.EventChannelEvent, EFI_TIMER_PERIOD_MILLISECONDS (100));
+    }
+  } else {
+    /* If the backend reads the state while we're erasing it then the
+     * ring state will become corrupted, preventing guest frontends from
+     * connecting. This is rare. To help diagnose the failure, we fill
+     * the ring with XS_INVALID packets. */
+    SetMem (xs.XenStore->req, XENSTORE_RING_SIZE, 0xff);
+    SetMem (xs.XenStore->rsp, XENSTORE_RING_SIZE, 0xff);
+    xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
+    xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
+  }
+  xs.XenStore = NULL;
+}
+
+//
+// Public API
+// API comments for these methods can be found in XenStore.h
+//
+
+XENSTORE_STATUS
+XenStoreListDirectory (
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *DirectoryPath,
+  IN  CONST CHAR8           *Node,
+  OUT UINT32                *DirectoryCountPtr,
+  OUT CONST CHAR8           ***DirectoryListPtr
+  )
+{
+  CHAR8 *Path;
+  CHAR8 *TempStr;
+  UINT32 Len = 0;
+  XENSTORE_STATUS Status;
+
+  Path = XenStoreJoin (DirectoryPath, Node);
+  Status = XenStoreSingle (Transaction, XS_DIRECTORY, Path, &Len,
+                           (VOID **) &TempStr);
+  FreePool (Path);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    return Status;
+  }
+
+  *DirectoryListPtr = Split (TempStr, Len, DirectoryCountPtr);
+
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+BOOLEAN
+XenStorePathExists (
+  IN XENSTORE_TRANSACTION  Transaction,
+  IN CONST CHAR8           *Directory,
+  IN CONST CHAR8           *Node
+  )
+{
+  CONST CHAR8 **TempStr;
+  XENSTORE_STATUS Status;
+  UINT32 TempNum;
+
+  Status = XenStoreListDirectory (Transaction, Directory, Node,
+                                  &TempNum, &TempStr);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    return FALSE;
+  }
+  FreePool (TempStr);
+  return TRUE;
+}
+
+XENSTORE_STATUS
+XenStoreRead (
+  IN  XENSTORE_TRANSACTION    Transaction,
+  IN  CONST CHAR8             *DirectoryPath,
+  IN  CONST CHAR8             *Node,
+  OUT UINT32                  *LenPtr OPTIONAL,
+  OUT VOID                    **Result
+  )
+{
+  CHAR8 *Path;
+  VOID *Value;
+  XENSTORE_STATUS Status;
+
+  Path = XenStoreJoin (DirectoryPath, Node);
+  Status = XenStoreSingle (Transaction, XS_READ, Path, LenPtr, &Value);
+  FreePool (Path);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    return Status;
+  }
+
+  *Result = Value;
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+XENSTORE_STATUS
+XenStoreWrite (
+  IN XENSTORE_TRANSACTION  Transaction,
+  IN CONST CHAR8           *DirectoryPath,
+  IN CONST CHAR8           *Node,
+  IN CONST CHAR8           *Str
+  )
+{
+  CHAR8 *Path;
+  WRITE_REQUEST WriteRequest[2];
+  XENSTORE_STATUS Status;
+
+  Path = XenStoreJoin (DirectoryPath, Node);
+
+  WriteRequest[0].Data = (VOID *) Path;
+  WriteRequest[0].Len = AsciiStrSize (Path);
+  WriteRequest[1].Data = (VOID *) Str;
+  WriteRequest[1].Len = AsciiStrLen (Str);
+
+  Status = XenStoreTalkv (Transaction, XS_WRITE, WriteRequest, 2, NULL, NULL);
+  FreePool (Path);
+
+  return Status;
+}
+
+XENSTORE_STATUS
+XenStoreRemove (
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *DirectoryPath,
+  IN CONST CHAR8            *Node
+  )
+{
+  CHAR8 *Path;
+  XENSTORE_STATUS Status;
+
+  Path = XenStoreJoin (DirectoryPath, Node);
+  Status = XenStoreSingle (Transaction, XS_RM, Path, NULL, NULL);
+  FreePool (Path);
+
+  return Status;
+}
+
+XENSTORE_STATUS
+XenStoreTransactionStart (
+  OUT XENSTORE_TRANSACTION  *Transaction
+  )
+{
+  CHAR8 *IdStr;
+  XENSTORE_STATUS Status;
+
+  Status = XenStoreSingle (XST_NIL, XS_TRANSACTION_START, "", NULL,
+                           (VOID **) &IdStr);
+  if (Status == XENSTORE_STATUS_SUCCESS) {
+    Transaction->Id = AsciiStrDecimalToUintn (IdStr);
+    FreePool (IdStr);
+  }
+
+  return Status;
+}
+
+XENSTORE_STATUS
+XenStoreTransactionEnd (
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN BOOLEAN                Abort
+  )
+{
+  CHAR8 AbortStr[2];
+
+  if (Abort) {
+    AsciiStrCpy (AbortStr, "F");
+  } else {
+    AsciiStrCpy (AbortStr, "T");
+  }
+
+  return XenStoreSingle (Transaction, XS_TRANSACTION_END, AbortStr, NULL, NULL);
+}
+
+XENSTORE_STATUS
+XenStoreVSPrint (
+  IN XENSTORE_TRANSACTION  Transaction,
+  IN CONST CHAR8           *DirectoryPath,
+  IN CONST CHAR8           *Node,
+  IN CONST CHAR8           *FormatString,
+  IN VA_LIST               Marker
+  )
+{
+  CHAR8 *Buf;
+  XENSTORE_STATUS Status;
+  UINTN BufSize;
+
+  BufSize = SPrintLengthAsciiFormat (FormatString, Marker) + 1;
+  Buf = AllocateZeroPool (BufSize);
+  AsciiVSPrint (Buf, BufSize, FormatString, Marker);
+  Status = XenStoreWrite (Transaction, DirectoryPath, Node, Buf);
+  FreePool (Buf);
+
+  return Status;
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenStoreSPrint (
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *DirectoryPath,
+  IN CONST CHAR8            *Node,
+  IN CONST CHAR8            *FormatString,
+  ...
+  )
+{
+  VA_LIST Marker;
+  XENSTORE_STATUS Status;
+
+  VA_START (Marker, FormatString);
+  Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
+  VA_END (Marker);
+
+  return Status;
+}
+
+XENSTORE_STATUS
+XenStoreRegisterWatch (
+  IN CONST CHAR8      *DirectoryPath,
+  IN CONST CHAR8      *Node,
+  OUT XENSTORE_WATCH  **WatchPtr
+  )
+{
+  /* Pointer in ascii is the token. */
+  CHAR8 Token[sizeof (XENSTORE_WATCH) * 2 + 1];
+  XENSTORE_STATUS Status;
+  XENSTORE_WATCH *Watch;
+
+  Watch = AllocateZeroPool (sizeof (XENSTORE_WATCH));
+  Watch->Signature = XENSTORE_WATCH_SIGNATURE;
+  Watch->Node = XenStoreJoin (DirectoryPath, Node);
+
+  EfiAcquireLock (&xs.RegisteredWatchesLock);
+  InsertTailList (&xs.RegisteredWatches, &Watch->Link);
+  EfiReleaseLock (&xs.RegisteredWatchesLock);
+
+  AsciiSPrint (Token, sizeof (Token), "%p", (VOID*) Watch);
+  Status = XenStoreWatch (Watch->Node, Token);
+
+  /* Ignore errors due to multiple registration. */
+  if (Status == XENSTORE_STATUS_EEXIST) {
+    Status = XENSTORE_STATUS_SUCCESS;
+  }
+
+  if (Status == XENSTORE_STATUS_SUCCESS) {
+    *WatchPtr = Watch;
+  } else {
+    EfiAcquireLock (&xs.RegisteredWatchesLock);
+    RemoveEntryList (&Watch->Link);
+    EfiReleaseLock (&xs.RegisteredWatchesLock);
+    FreePool (Watch->Node);
+    FreePool (Watch);
+  }
+
+  return Status;
+}
+
+VOID
+XenStoreUnregisterWatch (
+  IN XENSTORE_WATCH *Watch
+  )
+{
+  CHAR8 Token[sizeof (Watch) * 2 + 1];
+  LIST_ENTRY *Entry;
+
+  ASSERT (Watch->Signature == XENSTORE_WATCH_SIGNATURE);
+
+  AsciiSPrint (Token, sizeof (Token), "%p", (VOID *) Watch);
+  if (XenStoreFindWatch (Token) == NULL) {
+    return;
+  }
+
+  EfiAcquireLock (&xs.RegisteredWatchesLock);
+  RemoveEntryList (&Watch->Link);
+  EfiReleaseLock (&xs.RegisteredWatchesLock);
+
+  XenStoreUnwatch (Watch->Node, Token);
+
+  /* Cancel pending watch events. */
+  EfiAcquireLock (&xs.WatchEventsLock);
+  Entry = GetFirstNode (&xs.WatchEvents);
+  while (!IsNull (&xs.WatchEvents, Entry)) {
+    XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
+    Entry = GetNextNode (&xs.WatchEvents, Entry);
+    if (Message->u.Watch.Handle == Watch) {
+      RemoveEntryList (&Message->Link);
+      FreePool (Message->u.Watch.Vector);
+      FreePool (Message);
+    }
+  }
+  EfiReleaseLock (&xs.WatchEventsLock);
+
+  FreePool (Watch->Node);
+  FreePool (Watch);
+}
diff --git a/OvmfPkg/XenBusDxe/XenStore.h b/OvmfPkg/XenBusDxe/XenStore.h
new file mode 100644
index 0000000..f0dcb64
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenStore.h
@@ -0,0 +1,292 @@
+/** @file
+  Method declarations and structures for accessing the XenStore
+
+  Copyright (C) 2005 Rusty Russell, IBM Corporation
+  Copyright (C) 2005 XenSource Ltd.
+  Copyright (C) 2009,2010 Spectra Logic Corporation
+  Copyright (C) 2014, Citrix Ltd.
+
+  This file may be distributed separately from the Linux kernel, or
+  incorporated into other software packages, subject to the following license:
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this source file (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use, copy, modify,
+  merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  IN THE SOFTWARE.
+**/
+
+#ifndef _XEN_XENSTORE_XENSTOREVAR_H
+#define _XEN_XENSTORE_XENSTOREVAR_H
+
+#include "XenBusDxe.h"
+
+#include <IndustryStandard/Xen/io/xs_wire.h>
+
+typedef struct _XENSTORE_WATCH XENSTORE_WATCH;
+
+/**
+  Fetch the contents of a directory in the XenStore.
+
+  @param Transaction        The XenStore transaction covering this request.
+  @param DirectoryPath      The dirname of the path to read.
+  @param Node               The basename of the path to read.
+  @param DirectoryCountPtr  The returned number of directory entries.
+  @param DirectoryListPtr   An array of directory entry strings.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+
+  @note The results buffer is alloced and should be free'd by the
+        caller.
+**/
+XENSTORE_STATUS
+XenStoreListDirectory (
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *DirectoryPath,
+  IN  CONST CHAR8           *Node,
+  OUT UINT32                *DirectoryCountPtr,
+  OUT CONST CHAR8           ***DirectoryListPtr
+  );
+
+/**
+  Determine if a path exists in the XenStore.
+
+  @param Transaction  The XenStore transaction covering this request.
+  @param Directory    The dirname of the path to read.
+  @param Node         The basename of the path to read.
+
+  @retval TRUE  The path exists.
+  @retval FALSE The path does not exist or an error occurred attempting
+                to make that determination.
+**/
+BOOLEAN
+XenStorePathExists (
+  IN XENSTORE_TRANSACTION  Transaction,
+  IN CONST CHAR8 *Directory,
+  IN CONST CHAR8 *Node
+  );
+
+/**
+  Get the contents of a single "file".  Returns the contents in *Result which
+  should be freed after use.  The length of the value in bytes is returned in
+  *LenPtr.
+
+  @param Transaction    The XenStore transaction covering this request.
+  @param DirectoryPath  The dirname of the file to read.
+  @param Node           The basename of the file to read.
+  @param LenPtr         The amount of data read.
+  @param Result         The returned contents from this file.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+
+  @note The results buffer is malloced and should be free'd by the
+        caller.
+**/
+XENSTORE_STATUS
+XenStoreRead (
+  IN  XENSTORE_TRANSACTION    Transaction,
+  IN  CONST CHAR8             *DirectoryPath,
+  IN  CONST CHAR8             *Node,
+  OUT UINT32                  *LenPtr OPTIONAL,
+  OUT VOID                    **Result
+  );
+
+/**
+  Write to a single file.
+
+  @param Transaction    The XenStore transaction covering this request.
+  @param DirectoryPath  The dirname of the file to write.
+  @param Node           The basename of the file to write.
+  @param Str            The NUL terminated string of data to write.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+XENSTORE_STATUS
+XenStoreWrite (
+  IN XENSTORE_TRANSACTION  Transaction,
+  IN CONST CHAR8           *DirectoryPath,
+  IN CONST CHAR8           *Node,
+  IN CONST CHAR8           *Str
+  );
+
+/**
+  Remove a file or directory (directories must be empty).
+
+  @param Transaction    The XenStore transaction covering this request.
+  @param DirectoryPath  The dirname of the directory to remove.
+  @param Node           The basename of the directory to remove.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+XENSTORE_STATUS
+XenStoreRemove (
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *DirectoryPath,
+  IN CONST CHAR8            *Node
+  );
+
+/**
+  Start a transaction.
+
+  Changes by others will not be seen during the lifetime of this
+  transaction, and changes will not be visible to others until it
+  is committed (XenStoreTransactionEnd).
+
+  @param Transaction  The returned transaction.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+XENSTORE_STATUS
+XenStoreTransactionStart (
+  OUT XENSTORE_TRANSACTION  *Transaction
+  );
+
+/**
+  End a transaction.
+
+  @param Transaction  The transaction to end/commit.
+  @param Abort        If TRUE, the transaction is discarded
+                      instead of committed.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+XENSTORE_STATUS
+XenStoreTransactionEnd (
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN BOOLEAN                Abort
+  );
+
+/**
+  Printf formatted write to a XenStore file.
+
+  @param Transaction      The XenStore transaction covering this request.
+  @param DirectoryPath    The dirname of the path to read.
+  @param Node             The basename of the path to read.
+  @param FormatString     AsciiSPrint format string followed by a variable number
+                          of arguments.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of write failure.
+**/
+XENSTORE_STATUS
+EFIAPI
+XenStoreSPrint (
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *DirectoryPath,
+  IN CONST CHAR8            *Node,
+  IN CONST CHAR8            *FormatString,
+  ...
+  );
+
+/**
+  VA_LIST version of XenStoreSPrint().
+
+  @param Transaction    The XenStore transaction covering this request.
+  @param DirectoryPath  The dirname of the path to read.
+  @param Node           The basename of the path to read.
+  @param FormatString   Printf format string.
+  @param Marker         VA_LIST of printf arguments.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of write failure.
+**/
+XENSTORE_STATUS
+XenStoreVSPrint (
+  IN XENSTORE_TRANSACTION  Transaction,
+  IN CONST CHAR8           *DirectoryPath,
+  IN CONST CHAR8           *Node,
+  IN CONST CHAR8           *FormatString,
+  IN VA_LIST               Marker
+  );
+
+/**
+  Register a XenStore watch.
+
+  XenStore watches allow a client to be notified via a callback (embedded
+  within the watch object) of changes to an object in the XenStore.
+
+  @param DirectoryPath  The dirname of the path to watch.
+  @param Node           The basename of the path to watch.
+  @param WatchPtr       A returned XENSTORE_WATCH pointer.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of write failure.  EEXIST errors from the
+           XenStore are supressed, allowing multiple, physically different,
+           xenbus_watch objects, to watch the same path in the XenStore.
+**/
+XENSTORE_STATUS
+XenStoreRegisterWatch (
+  IN  CONST CHAR8     *DirectoryPath,
+  IN  CONST CHAR8     *Node,
+  OUT XENSTORE_WATCH  **WatchPtr
+  );
+
+/**
+  Unregister a XenStore watch.
+
+  @param Watch  An XENSTORE_WATCH object previously returned by a successful
+                call to XenStoreRegisterWatch ().
+**/
+VOID
+XenStoreUnregisterWatch (
+  IN XENSTORE_WATCH *Watch
+  );
+
+/**
+  Allocate and return the XenStore path string <DirectoryPath>/<Node>.  If name
+  is the NUL string, the returned value contains the path string
+  <DirectoryPath>.
+
+  @param DirectoryPath	The NUL terminated directory prefix for new path.
+  @param Node           The NUL terminated basename for the new path.
+
+  @return  A buffer containing the joined path.
+ */
+CHAR8 *
+XenStoreJoin (
+  IN CONST CHAR8 *DirectoryPath,
+  IN CONST CHAR8 *Node
+  );
+
+
+/**
+  Initialize the XenStore states and rings.
+
+  @param Dev  A pointer to a XENBUS_DEVICE instance.
+
+  @return     EFI_SUCCESS if everything went smoothly.
+**/
+EFI_STATUS
+XenStoreInit (
+  XENBUS_DEVICE *Dev
+  );
+
+/**
+  Deinitialize the XenStore states and rings.
+
+  @param Dev  A pointer to a XENBUS_DEVICE instance.
+**/
+VOID
+XenStoreDeinit (
+  IN XENBUS_DEVICE *Dev
+  );
+
+#endif /* _XEN_XENSTORE_XENSTOREVAR_H */
-- 
Anthony PERARD

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

* [PATCH v3 13/19] OvmfPkg/XenBusDxe: Add an helper AsciiStrDup.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (11 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 12/19] OvmfPkg/XenBusDxe: Add XenStore client implementation Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 14/19] OvmfPkg/XenBusDxe: Add XenStore function into the XenBus protocol Anthony PERARD
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

.. because we need it in the patch titled:
"OvmfPkg/XenBusDxe: Indroduce XenBus support itself."

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
 OvmfPkg/XenBusDxe/Helpers.c   | 9 +++++++++
 OvmfPkg/XenBusDxe/XenBusDxe.h | 5 +++++
 2 files changed, 14 insertions(+)
 create mode 100644 OvmfPkg/XenBusDxe/Helpers.c

diff --git a/OvmfPkg/XenBusDxe/Helpers.c b/OvmfPkg/XenBusDxe/Helpers.c
new file mode 100644
index 0000000..3e938b6
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/Helpers.c
@@ -0,0 +1,9 @@
+#include "XenBusDxe.h"
+
+CHAR8*
+AsciiStrDup (
+  IN CONST CHAR8* Str
+  )
+{
+  return AllocateCopyPool (AsciiStrSize (Str), Str);
+}
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 4a0f402..9f89c94 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -132,4 +132,9 @@ TestAndClearBit (
   IN volatile VOID *Address
   );
 
+CHAR8*
+AsciiStrDup (
+  IN CONST CHAR8* Str
+  );
+
 #endif
-- 
Anthony PERARD

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

* [PATCH v3 14/19] OvmfPkg/XenBusDxe: Add XenStore function into the XenBus protocol
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (12 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 13/19] OvmfPkg/XenBusDxe: Add an helper AsciiStrDup Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce XenBus support itself Anthony PERARD
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Change in V3:
- Have XenStoreWaitWatch/XenBusWaitForWatch return a XENSTORE_STATUS
  instead of VOID.
- Add description of the introducted member of the protocol.
---
 OvmfPkg/Include/Protocol/XenBus.h | 223 ++++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenStore.c      | 164 ++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenStore.h      |  87 +++++++++++++++
 3 files changed, 474 insertions(+)

diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h
index 2c28a97..47750af 100644
--- a/OvmfPkg/Include/Protocol/XenBus.h
+++ b/OvmfPkg/Include/Protocol/XenBus.h
@@ -85,6 +85,136 @@ typedef enum {
 ///
 
 /**
+  Get the contents of the node Node of the PV device. Returns the contents in
+  *Result which should be freed after use.
+
+  @param This           A pointer to XENBUS_PROTOCOL instance.
+  @param Transaction    The XenStore transaction covering this request.
+  @param Node           The basename of the file to read.
+  @param Result         The returned contents from this file.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+
+  @note The results buffer is malloced and should be free'd by the
+        caller.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_XS_READ)(
+  IN  XENBUS_PROTOCOL       *This,
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *Node,
+  OUT VOID                  **Result
+  );
+
+/**
+  Get the contents of the node Node of the PV device's backend. Returns the
+  contents in *Result which should be freed after use.
+
+  @param This           A pointer to XENBUS_PROTOCOL instance.
+  @param Transaction    The XenStore transaction covering this request.
+  @param Node           The basename of the file to read.
+  @param Result         The returned contents from this file.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+
+  @note The results buffer is malloced and should be free'd by the
+        caller.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_XS_BACKEND_READ)(
+  IN  XENBUS_PROTOCOL       *This,
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *Node,
+  OUT VOID                  **Result
+  );
+
+/**
+  Print formatted write to a XenStore node.
+
+  @param This             A pointer to XENBUS_PROTOCOL instance.
+  @param Transaction      The XenStore transaction covering this request.
+  @param Directory        The dirname of the path to read.
+  @param Node             The basename of the path to read.
+  @param Format           AsciiSPrint format string followed by a variable number
+                          of arguments.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of write failure.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_XS_PRINTF) (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *Directory,
+  IN CONST CHAR8            *Node,
+  IN CONST CHAR8            *Format,
+  ...
+  );
+
+/**
+  Remove a node or directory (directories must be empty) of the PV driver's
+  subdirectory.
+
+  @param This           A pointer to XENBUS_PROTOCOL instance.
+  @param Transaction    The XenStore transaction covering this request.
+  @param Node           The basename of the node to remove.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_XS_REMOVE) (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *Node
+  );
+
+/**
+  Start a transaction.
+
+  Changes by others will not be seen during the lifetime of this
+  transaction, and changes will not be visible to others until it
+  is committed (XsTransactionEnd).
+
+  @param This         A pointer to XENBUS_PROTOCOL instance.
+  @param Transaction  The returned transaction.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_XS_TRANSACTION_START)(
+  IN  XENBUS_PROTOCOL       *This,
+  OUT XENSTORE_TRANSACTION  *Transaction
+  );
+
+/**
+  End a transaction.
+
+  @param This         A pointer to XENBUS_PROTOCOL instance.
+  @param Transaction  The transaction to end/commit.
+  @param Abort        If TRUE, the transaction is discarded
+                      instead of committed.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_XS_TRANSACTION_END) (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN BOOLEAN                Abort
+  );
+
+/**
   Grant access to the page Frame to the domain DomainId.
 
   @param This       A pointer to XENBUS_PROTOCOL instance.
@@ -117,6 +247,83 @@ EFI_STATUS
   IN grant_ref_t      Ref
   );
 
+/**
+  Register a XenStore watch.
+
+  XenStore watches allow a client to wait for changes to an object in the
+  XenStore.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param Node       The basename of the path to watch.
+  @param Token      A token.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of write failure.  EEXIST errors from the
+           XenStore are supressed, allowing multiple, physically different,
+           xenbus_watch objects, to watch the same path in the XenStore.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_REGISTER_WATCH) (
+  IN  XENBUS_PROTOCOL *This,
+  IN  CONST CHAR8     *Node,
+  OUT VOID            **Token
+  );
+
+/**
+  Register a XenStore watch on a backend's node.
+
+  XenStore watches allow a client to wait for changes to an object in the
+  XenStore.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param Node       The basename of the path to watch.
+  @param Token      A token.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of write failure.  EEXIST errors from the
+           XenStore are supressed, allowing multiple, physically different,
+           xenbus_watch objects, to watch the same path in the XenStore.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_REGISTER_WATCH_BACKEND) (
+  IN  XENBUS_PROTOCOL *This,
+  IN  CONST CHAR8     *Node,
+  OUT VOID            **Token
+  );
+
+/**
+  Unregister a XenStore watch.
+
+  @param This   A pointer to the XENBUS_PROTOCOL.
+  @param Token  An token previously returned by a successful
+                call to RegisterWatch ().
+**/
+typedef
+VOID
+(EFIAPI *XENBUS_UNREGISTER_WATCH) (
+  IN XENBUS_PROTOCOL  *This,
+  IN VOID             *Token
+  );
+
+/**
+  Block until the node watch by Token change.
+
+  @param This   A pointer to the XENBUS_PROTOCOL.
+  @param Token  An token previously returned by a successful
+                call to RegisterWatch or RegisterWatchBackend.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_WAIT_FOR_WATCH) (
+  IN XENBUS_PROTOCOL  *This,
+  IN VOID             *Token
+  );
+
 
 ///
 /// Protocol structure
@@ -125,11 +332,27 @@ EFI_STATUS
 /// should not be used outside of the EDK II tree.
 ///
 struct _XENBUS_PROTOCOL {
+  XENBUS_XS_READ                XsRead;
+  XENBUS_XS_BACKEND_READ        XsBackendRead;
+  XENBUS_XS_PRINTF              XsPrintf;
+  XENBUS_XS_REMOVE              XsRemove;
+  XENBUS_XS_TRANSACTION_START   XsTransactionStart;
+  XENBUS_XS_TRANSACTION_END     XsTransactionEnd;
+
   XENBUS_GRANT_ACCESS           GrantAccess;
   XENBUS_GRANT_END_ACCESS       GrantEndAccess;
+
+  XENBUS_REGISTER_WATCH         RegisterWatch;
+  XENBUS_REGISTER_WATCH_BACKEND RegisterWatchBackend;
+  XENBUS_UNREGISTER_WATCH       UnregisterWatch;
+  XENBUS_WAIT_FOR_WATCH         WaitForWatch;
   //
   // Protocol data fields
   //
+  CONST CHAR8                   *Type;
+  UINT16                        DeviceId;
+  CONST CHAR8                   *Node;
+  CONST CHAR8                   *Backend;
 };
 
 extern EFI_GUID gXenBusProtocolGuid;
diff --git a/OvmfPkg/XenBusDxe/XenStore.c b/OvmfPkg/XenBusDxe/XenStore.c
index 8ba4328..4af4c6e 100644
--- a/OvmfPkg/XenBusDxe/XenStore.c
+++ b/OvmfPkg/XenBusDxe/XenStore.c
@@ -941,6 +941,46 @@ XenStoreUnwatch (
   return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL);
 }
 
+STATIC
+XENSTORE_STATUS
+XenStoreWaitWatch (
+  VOID *Token
+  )
+{
+  XENSTORE_MESSAGE *Message;
+  LIST_ENTRY *Entry = NULL;
+  LIST_ENTRY *Last = NULL;
+  XENSTORE_STATUS Status;
+
+  while (TRUE) {
+    EfiAcquireLock (&xs.WatchEventsLock);
+    if (IsListEmpty (&xs.WatchEvents) ||
+        Last == GetFirstNode (&xs.WatchEvents)) {
+      EfiReleaseLock (&xs.WatchEventsLock);
+      Status = XenStoreProcessMessage ();
+      if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) {
+        return Status;
+      }
+      continue;
+    }
+
+    for (Entry = GetFirstNode (&xs.WatchEvents);
+         Entry != Last && !IsNull (&xs.WatchEvents, Entry);
+         Entry = GetNextNode (&xs.WatchEvents, Entry)) {
+      Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
+      if (Message->u.Watch.Handle == Token) {
+        RemoveEntryList (Entry);
+        EfiReleaseLock (&xs.WatchEventsLock);
+        FreePool(Message->u.Watch.Vector);
+        FreePool(Message);
+        return XENSTORE_STATUS_SUCCESS;
+      }
+    }
+    Last = GetFirstNode (&xs.WatchEvents);
+    EfiReleaseLock (&xs.WatchEventsLock);
+  }
+}
+
 VOID
 EFIAPI
 NotifyEventChannelCheckForEvent (
@@ -1384,3 +1424,127 @@ XenStoreUnregisterWatch (
   FreePool (Watch->Node);
   FreePool (Watch);
 }
+
+
+//
+// XENBUS protocol
+//
+
+XENSTORE_STATUS
+EFIAPI
+XenBusWaitForWatch (
+  IN XENBUS_PROTOCOL *This,
+  IN VOID *Token
+  )
+{
+  return XenStoreWaitWatch (Token);
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreRead (
+  IN  XENBUS_PROTOCOL       *This,
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *Node,
+  OUT VOID                  **Value
+  )
+{
+  return XenStoreRead (Transaction, This->Node, Node, NULL, Value);
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreBackendRead (
+  IN  XENBUS_PROTOCOL       *This,
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *Node,
+  OUT VOID                  **Value
+  )
+{
+  return XenStoreRead (Transaction, This->Backend, Node, NULL, Value);
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreRemove (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN const char             *Node
+  )
+{
+  return XenStoreRemove (Transaction, This->Node, Node);
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreTransactionStart (
+  IN  XENBUS_PROTOCOL       *This,
+  OUT XENSTORE_TRANSACTION  *Transaction
+  )
+{
+  return XenStoreTransactionStart (Transaction);
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreTransactionEnd (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN BOOLEAN                Abort
+  )
+{
+  return XenStoreTransactionEnd (Transaction, Abort);
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreSPrint (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *DirectoryPath,
+  IN CONST CHAR8            *Node,
+  IN CONST CHAR8            *FormatString,
+  ...
+  )
+{
+  VA_LIST Marker;
+  XENSTORE_STATUS Status;
+
+  VA_START (Marker, FormatString);
+  Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
+  VA_END (Marker);
+
+  return Status;
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusRegisterWatch (
+  IN  XENBUS_PROTOCOL *This,
+  IN  CONST CHAR8     *Node,
+  OUT VOID            **Token
+  )
+{
+  return XenStoreRegisterWatch (This->Node, Node, (XENSTORE_WATCH **) Token);
+}
+
+XENSTORE_STATUS
+EFIAPI
+XenBusRegisterWatchBackend (
+  IN  XENBUS_PROTOCOL *This,
+  IN  CONST CHAR8     *Node,
+  OUT VOID            **Token
+  )
+{
+  return XenStoreRegisterWatch (This->Backend, Node, (XENSTORE_WATCH **) Token);
+}
+
+VOID
+EFIAPI
+XenBusUnregisterWatch (
+  IN XENBUS_PROTOCOL  *This,
+  IN VOID             *Token
+  )
+{
+  XenStoreUnregisterWatch ((XENSTORE_WATCH *) Token);
+}
diff --git a/OvmfPkg/XenBusDxe/XenStore.h b/OvmfPkg/XenBusDxe/XenStore.h
index f0dcb64..b3c5c6e 100644
--- a/OvmfPkg/XenBusDxe/XenStore.h
+++ b/OvmfPkg/XenBusDxe/XenStore.h
@@ -289,4 +289,91 @@ XenStoreDeinit (
   IN XENBUS_DEVICE *Dev
   );
 
+
+//
+// XENBUS protocol
+//
+
+XENSTORE_STATUS
+EFIAPI
+XenBusWaitForWatch (
+  IN XENBUS_PROTOCOL *This,
+  IN VOID *Token
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreRead (
+  IN  XENBUS_PROTOCOL       *This,
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *Node,
+  OUT VOID                  **Value
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreBackendRead (
+  IN  XENBUS_PROTOCOL       *This,
+  IN  XENSTORE_TRANSACTION  Transaction,
+  IN  CONST CHAR8           *Node,
+  OUT VOID                  **Value
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreRemove (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *Node
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreTransactionStart (
+  IN  XENBUS_PROTOCOL       *This,
+  OUT XENSTORE_TRANSACTION  *Transaction
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreTransactionEnd (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN BOOLEAN                Abort
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusXenStoreSPrint (
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN CONST CHAR8            *DirectoryPath,
+  IN CONST CHAR8            *Node,
+  IN CONST CHAR8            *FormatString,
+  ...
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusRegisterWatch (
+  IN  XENBUS_PROTOCOL *This,
+  IN  CONST CHAR8     *Node,
+  OUT VOID            **Token
+  );
+
+XENSTORE_STATUS
+EFIAPI
+XenBusRegisterWatchBackend (
+  IN  XENBUS_PROTOCOL *This,
+  IN  CONST CHAR8     *Node,
+  OUT VOID            **Token
+  );
+
+VOID
+EFIAPI
+XenBusUnregisterWatch (
+  IN XENBUS_PROTOCOL  *This,
+  IN VOID             *Token
+  );
+
 #endif /* _XEN_XENSTORE_XENSTOREVAR_H */
-- 
Anthony PERARD

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

* [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce XenBus support itself.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (13 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 14/19] OvmfPkg/XenBusDxe: Add XenStore function into the XenBus protocol Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:03 ` [PATCH v3 16/19] OvmfPkg/XenBusDxe: Add Event Channel into XenBus protocol Anthony PERARD
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This is a bus-like on top of XenStore. It will look for advertised
ParaVirtualized devices and initialize them by producing XenBus
protocol.

Origin: FreeBSD 10.0

License: This patch adds XenBus.c which is under the MIT licence.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- Insert to ChildList later, once populated.
- Remove XENBUS_XENSTORE_NODE macro.
- add comment to XenBusAddDevice and XenBusEnumerateBus about
  concurrency calls.
- Add a description to the introduced member to the protocol.

Change in V2:
- comment, file header
- Fix comment style
- Error handling in the main init function
- coding style
- Fix error path in add device.
---
 OvmfPkg/Include/Protocol/XenBus.h |  19 ++
 OvmfPkg/XenBusDxe/XenBus.c        | 372 ++++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenBus.h        |  64 +++++++
 OvmfPkg/XenBusDxe/XenBusDxe.c     |  66 +++++++
 OvmfPkg/XenBusDxe/XenBusDxe.h     |  19 ++
 OvmfPkg/XenBusDxe/XenBusDxe.inf   |   3 +
 6 files changed, 543 insertions(+)
 create mode 100644 OvmfPkg/XenBusDxe/XenBus.c
 create mode 100644 OvmfPkg/XenBusDxe/XenBus.h

diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h
index 47750af..e54077d 100644
--- a/OvmfPkg/Include/Protocol/XenBus.h
+++ b/OvmfPkg/Include/Protocol/XenBus.h
@@ -215,6 +215,24 @@ XENSTORE_STATUS
   );
 
 /**
+  Set a new state for the frontend of the PV driver.
+
+  @param This         A pointer to XENBUS_PROTOCOL instance.
+  @param Transaction  The transaction to end/commit.
+  @param State        The new state to apply.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+**/
+typedef
+XENSTORE_STATUS
+(EFIAPI *XENBUS_SET_STATE)(
+  IN XENBUS_PROTOCOL        *This,
+  IN XENSTORE_TRANSACTION   Transaction,
+  IN XenBusState            State
+  );
+
+/**
   Grant access to the page Frame to the domain DomainId.
 
   @param This       A pointer to XENBUS_PROTOCOL instance.
@@ -338,6 +356,7 @@ struct _XENBUS_PROTOCOL {
   XENBUS_XS_REMOVE              XsRemove;
   XENBUS_XS_TRANSACTION_START   XsTransactionStart;
   XENBUS_XS_TRANSACTION_END     XsTransactionEnd;
+  XENBUS_SET_STATE              SetState;
 
   XENBUS_GRANT_ACCESS           GrantAccess;
   XENBUS_GRANT_END_ACCESS       GrantEndAccess;
diff --git a/OvmfPkg/XenBusDxe/XenBus.c b/OvmfPkg/XenBusDxe/XenBus.c
new file mode 100644
index 0000000..e595767
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenBus.c
@@ -0,0 +1,372 @@
+/** @file
+  XenBus Bus driver implemtation.
+
+  This file implement the necessary to discover and enumerate Xen PV devices
+  through XenStore.
+
+  Copyright (C) 2010 Spectra Logic Corporation
+  Copyright (C) 2008 Doug Rabson
+  Copyright (C) 2005 Rusty Russell, IBM Corporation
+  Copyright (C) 2005 Mike Wray, Hewlett-Packard
+  Copyright (C) 2005 XenSource Ltd
+  Copyright (C) 2014, Citrix Ltd.
+
+  This file may be distributed separately from the Linux kernel, or
+  incorporated into other software packages, subject to the following license:
+
+  Permission is hereby granted, free of charge, to any person obtaining a copy
+  of this source file (the "Software"), to deal in the Software without
+  restriction, including without limitation the rights to use, copy, modify,
+  merge, publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+
+  The above copyright notice and this permission notice shall be included in
+  all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+  IN THE SOFTWARE.
+**/
+
+#include <Library/PrintLib.h>
+
+#include "XenBus.h"
+#include "GrantTable.h"
+#include "XenStore.h"
+#include "EventChannel.h"
+
+#include <IndustryStandard/Xen/io/xenbus.h>
+
+STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData;
+
+STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate = {
+  .Vendor.Header.Type = HARDWARE_DEVICE_PATH,
+  .Vendor.Header.SubType = HW_VENDOR_DP,
+  .Vendor.Header.Length[0] = (UINT8) sizeof (XENBUS_DEVICE_PATH),
+  .Vendor.Header.Length[1] = (UINT8) (sizeof (XENBUS_DEVICE_PATH) >> 8),
+  .Vendor.Guid = XENBUS_PROTOCOL_GUID,
+  .Type = 0,
+  .DeviceId = 0
+};
+
+
+/**
+  Search our internal record of configured devices (not the XenStore) to
+  determine if the XenBus device indicated by Node is known to the system.
+
+  @param Dev   The XENBUS_DEVICE instance to search for device children.
+  @param Node  The XenStore node path for the device to find.
+
+  @return  The XENBUS_PRIVATE_DATA of the found device if any, or NULL.
+ */
+STATIC
+XENBUS_PRIVATE_DATA *
+XenBusDeviceInitialized (
+  IN XENBUS_DEVICE *Dev,
+  IN CONST CHAR8 *Node
+  )
+{
+  LIST_ENTRY *Entry;
+  XENBUS_PRIVATE_DATA *Child;
+  XENBUS_PRIVATE_DATA *Result;
+
+  if (IsListEmpty (&Dev->ChildList)) {
+    return NULL;
+  }
+
+  Result = NULL;
+  for (Entry = GetFirstNode (&Dev->ChildList);
+       !IsNodeAtEnd (&Dev->ChildList, Entry);
+       Entry = GetNextNode (&Dev->ChildList, Entry)) {
+    Child = XENBUS_PRIVATE_DATA_FROM_LINK (Entry);
+    if (!AsciiStrCmp (Child->XenBusIo.Node, Node)) {
+      Result = Child;
+      break;
+    }
+  }
+
+  return (Result);
+}
+
+STATIC
+XenbusState
+XenBusReadDriverState (
+  IN CONST CHAR8 *Path
+  )
+{
+  XenbusState State;
+  CHAR8 *Ptr = NULL;
+  XENSTORE_STATUS Status;
+
+  Status = XenStoreRead (XST_NIL, Path, "state", NULL, (VOID **)&Ptr);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    State = XenbusStateClosed;
+  } else {
+    State = AsciiStrDecimalToUintn (Ptr);
+  }
+
+  if (Ptr != NULL) {
+    FreePool (Ptr);
+  }
+
+  return State;
+}
+
+//
+// Callers should ensure that they are only one calling XenBusAddDevice.
+//
+STATIC
+EFI_STATUS
+XenBusAddDevice (
+  XENBUS_DEVICE *Dev,
+  CONST CHAR8 *Type,
+  CONST CHAR8 *Id)
+{
+  CHAR8 DevicePath[XENSTORE_ABS_PATH_MAX];
+  XENSTORE_STATUS StatusXenStore;
+  XENBUS_PRIVATE_DATA *Private;
+  EFI_STATUS Status;
+  XENBUS_DEVICE_PATH *TempXenBusPath;
+  VOID *ChildPciIo;
+
+  AsciiSPrint (DevicePath, sizeof (DevicePath),
+               "device/%a/%a", Type, Id);
+
+  if (XenStorePathExists (XST_NIL, DevicePath, "")) {
+    XENBUS_PRIVATE_DATA *Child;
+    enum xenbus_state State;
+    CHAR8 *BackendPath;
+
+    Child = XenBusDeviceInitialized (Dev, DevicePath);
+    if (Child != NULL) {
+      /*
+       * We are already tracking this node
+       */
+      Status = EFI_SUCCESS;
+      goto out;
+    }
+
+    State = XenBusReadDriverState (DevicePath);
+    if (State != XenbusStateInitialising) {
+      /*
+       * Device is not new, so ignore it. This can
+       * happen if a device is going away after
+       * switching to Closed.
+       */
+      DEBUG ((EFI_D_INFO, "XenBus: Device %a ignored. "
+              "State %d\n", DevicePath, State));
+      Status = EFI_SUCCESS;
+      goto out;
+    }
+
+    StatusXenStore = XenStoreRead (XST_NIL, DevicePath, "backend",
+                                   NULL, (VOID **) &BackendPath);
+    if (StatusXenStore != XENSTORE_STATUS_SUCCESS) {
+      DEBUG ((EFI_D_ERROR, "xenbus: %a no backend path.\n", DevicePath));
+      Status = EFI_NOT_FOUND;
+      goto out;
+    }
+
+    Private = AllocateCopyPool (sizeof (*Private), &gXenBusPrivateData);
+    Private->XenBusIo.Type = AsciiStrDup (Type);
+    Private->XenBusIo.Node = AsciiStrDup (DevicePath);
+    Private->XenBusIo.Backend = BackendPath;
+    Private->XenBusIo.DeviceId = AsciiStrDecimalToUintn (Id);
+    Private->Dev = Dev;
+
+    TempXenBusPath = AllocateCopyPool (sizeof (XENBUS_DEVICE_PATH),
+                                       &gXenBusDevicePathTemplate);
+    if (!AsciiStrCmp (Private->XenBusIo.Type, "vbd")) {
+      TempXenBusPath->Type = XENBUS_DEVICE_PATH_TYPE_VBD;
+    }
+    TempXenBusPath->DeviceId = Private->XenBusIo.DeviceId;
+    Private->DevicePath = (XENBUS_DEVICE_PATH *)AppendDevicePathNode (
+                            Dev->DevicePath,
+                            &TempXenBusPath->Vendor.Header);
+    FreePool (TempXenBusPath);
+
+    InsertTailList (&Dev->ChildList, &Private->Link);
+
+    Status = gBS->InstallMultipleProtocolInterfaces (
+               &Private->Handle,
+               &gEfiDevicePathProtocolGuid, Private->DevicePath,
+               &gXenBusProtocolGuid, &Private->XenBusIo,
+               NULL);
+    if (EFI_ERROR (Status)) {
+      goto ErrorInstallProtocol;
+    }
+
+    Status = gBS->OpenProtocol (Dev->ControllerHandle,
+               &gEfiPciIoProtocolGuid,
+               &ChildPciIo, Dev->This->DriverBindingHandle,
+               Private->Handle,
+               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "open by child controller fail (%r)\n",
+              Status));
+      goto ErrorOpenProtocolByChild;
+    }
+  } else {
+    DEBUG ((EFI_D_ERROR, "XenBus: does not exist: %a\n", DevicePath));
+    Status = EFI_NOT_FOUND;
+  }
+
+  return Status;
+
+ErrorOpenProtocolByChild:
+  gBS->UninstallMultipleProtocolInterfaces (
+    &Private->Handle,
+    &gEfiDevicePathProtocolGuid, Private->DevicePath,
+    &gXenBusProtocolGuid, &Private->XenBusIo,
+    NULL);
+ErrorInstallProtocol:
+  RemoveEntryList (&Private->Link);
+  FreePool (Private->DevicePath);
+  FreePool ((VOID *) Private->XenBusIo.Backend);
+  FreePool ((VOID *) Private->XenBusIo.Node);
+  FreePool ((VOID *) Private->XenBusIo.Type);
+  FreePool (Private);
+out:
+  return Status;
+}
+
+/**
+  Enumerate all devices of the given type on this bus.
+
+  @param Dev   A XENBUS_DEVICE instance.
+  @param Type  String indicating the device sub-tree (e.g. "vfb", "vif")
+               to enumerate.
+
+  Devices that are found are been initialize via XenBusAddDevice ().
+  XenBusAddDevice () ignores duplicate detects and ignores duplicate devices,
+  so it can be called unconditionally for any device found in the XenStore.
+ */
+STATIC
+VOID
+XenBusEnumerateDeviceType (
+  XENBUS_DEVICE *Dev,
+  CONST CHAR8 *Type
+  )
+{
+  CONST CHAR8 **Directory;
+  UINTN Index;
+  UINT32 Count;
+  XENSTORE_STATUS Status;
+
+  Status = XenStoreListDirectory (XST_NIL,
+                                  "device", Type,
+                                  &Count, &Directory);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    return;
+  }
+  for (Index = 0; Index < Count; Index++) {
+    XenBusAddDevice (Dev, Type, Directory[Index]);
+  }
+
+  FreePool (Directory);
+}
+
+
+/**
+  Enumerate the devices on a XenBus bus and install a XenBus Protocol instance.
+
+  Caller should ensure that it is the only one to call this function. This
+  function cannot be called concurrently.
+
+  @param Dev   A XENBUS_DEVICE instance.
+
+  @return  On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+           indicating the type of failure.
+ */
+XENSTORE_STATUS
+XenBusEnumerateBus (
+  XENBUS_DEVICE *Dev
+  )
+{
+  CONST CHAR8 **Types;
+  UINTN Index;
+  UINT32 Count;
+  XENSTORE_STATUS Status;
+
+  Status = XenStoreListDirectory (XST_NIL,
+                                  "device", "",
+                                  &Count, &Types);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    return Status;
+  }
+
+  for (Index = 0; Index < Count; Index++) {
+    XenBusEnumerateDeviceType (Dev, Types[Index]);
+  }
+
+  FreePool (Types);
+
+  return XENSTORE_STATUS_SUCCESS;
+}
+
+STATIC
+XENSTORE_STATUS
+EFIAPI
+XenBusSetState (
+  IN XENBUS_PROTOCOL      *This,
+  IN XENSTORE_TRANSACTION Transaction,
+  IN enum xenbus_state    NewState
+  )
+{
+  enum xenbus_state CurrentState;
+  XENSTORE_STATUS Status;
+  CHAR8 *Temp;
+
+  DEBUG ((EFI_D_INFO, "XenBus: Set state to %d\n", NewState));
+
+  Status = XenStoreRead (Transaction, This->Node, "state", NULL, (VOID **)&Temp);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    goto Out;
+  }
+  CurrentState = AsciiStrDecimalToUintn (Temp);
+  FreePool (Temp);
+  if (CurrentState == NewState) {
+    goto Out;
+  }
+
+  do {
+    Status = XenStoreSPrint (Transaction, This->Node, "state", "%d", NewState);
+  } while (Status == XENSTORE_STATUS_EAGAIN);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR, "XenBus: failed to write new state\n"));
+    goto Out;
+  }
+  DEBUG ((EFI_D_INFO, "XenBus: Set state to %d, done\n", NewState));
+
+Out:
+  return Status;
+}
+
+STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = {
+  .Signature = XENBUS_PRIVATE_DATA_SIGNATURE,
+
+  .XenBusIo.XsRead = XenBusXenStoreRead,
+  .XenBusIo.XsBackendRead = XenBusXenStoreBackendRead,
+  .XenBusIo.XsPrintf = XenBusXenStoreSPrint,
+  .XenBusIo.XsRemove = XenBusXenStoreRemove,
+  .XenBusIo.XsTransactionStart = XenBusXenStoreTransactionStart,
+  .XenBusIo.XsTransactionEnd = XenBusXenStoreTransactionEnd,
+  .XenBusIo.SetState = XenBusSetState,
+  .XenBusIo.GrantAccess = XenBusGrantAccess,
+  .XenBusIo.GrantEndAccess = XenBusGrantEndAccess,
+  .XenBusIo.RegisterWatch = XenBusRegisterWatch,
+  .XenBusIo.RegisterWatchBackend = XenBusRegisterWatchBackend,
+  .XenBusIo.UnregisterWatch = XenBusUnregisterWatch,
+  .XenBusIo.WaitForWatch = XenBusWaitForWatch,
+
+  .XenBusIo.Type = NULL,
+  .XenBusIo.Node = NULL,
+  .XenBusIo.Backend = NULL,
+
+  .Dev = NULL
+};
diff --git a/OvmfPkg/XenBusDxe/XenBus.h b/OvmfPkg/XenBusDxe/XenBus.h
new file mode 100644
index 0000000..7ff25c3
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenBus.h
@@ -0,0 +1,64 @@
+/** @file
+  Core definitions and data structures shareable across OS platforms.
+
+  Copyright (c) 2010 Spectra Logic Corporation
+  Copyright (C) 2008 Doug Rabson
+  All rights reserved.
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions, and the following disclaimer,
+     without modification.
+  2. Redistributions in binary form must reproduce at minimum a disclaimer
+     substantially similar to the "NO WARRANTY" disclaimer below
+     ("Disclaimer") and any redistribution must be conditioned upon
+     including a substantially similar Disclaimer requirement for further
+     binary redistribution.
+
+  NO WARRANTY
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGES.
+
+**/
+#ifndef _XEN_XENBUS_XENBUSB_H
+#define _XEN_XENBUS_XENBUSB_H
+
+#include "XenBusDxe.h"
+
+#define XENBUS_DEVICE_PATH_TYPE_VBD 0x1
+struct _XENBUS_DEVICE_PATH {
+  VENDOR_DEVICE_PATH  Vendor;
+  UINT8               Type;
+  UINT16              DeviceId;
+};
+
+
+/**
+  Perform XenBus bus enumeration and install protocol for children.
+
+  Caller should ensure that it is the only one to call this function. This
+  function cannot be called concurrently.
+
+  @param Dev   The NewBus device representing this XenBus bus.
+
+  @return      On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
+               indicating the type of failure.
+**/
+XENSTORE_STATUS
+XenBusEnumerateBus (
+  XENBUS_DEVICE *Dev
+  );
+
+#endif /* _XEN_XENBUS_XENBUSB_H */
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index 69e1609..295dbd1 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -48,6 +48,7 @@
 #include "XenHypercall.h"
 #include "GrantTable.h"
 #include "XenStore.h"
+#include "XenBus.h"
 
 
 ///
@@ -302,6 +303,7 @@ XenBusDxeDriverBindingStart (
   EFI_PCI_IO_PROTOCOL *PciIo;
   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
   UINT64 MmioAddr;
+  EFI_DEVICE_PATH_PROTOCOL *DevicePath;
 
   Status = gBS->OpenProtocol (
                      ControllerHandle,
@@ -315,11 +317,26 @@ XenBusDxeDriverBindingStart (
     return Status;
   }
 
+  Status = gBS->OpenProtocol (
+                  ControllerHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID **) &DevicePath,
+                  This->DriverBindingHandle,
+                  ControllerHandle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+
+  if (EFI_ERROR (Status)) {
+    goto ErrorOpenningProtocol;
+  }
+
   Dev = AllocateZeroPool (sizeof (*Dev));
   Dev->Signature = XENBUS_DEVICE_SIGNATURE;
   Dev->This = This;
   Dev->ControllerHandle = ControllerHandle;
   Dev->PciIo = PciIo;
+  Dev->DevicePath = DevicePath;
+  InitializeListHead (&Dev->ChildList);
 
   EfiAcquireLock (&mMyDeviceLock);
   if (mMyDevice != NULL) {
@@ -366,6 +383,8 @@ XenBusDxeDriverBindingStart (
   Status = XenStoreInit (Dev);
   ASSERT_EFI_ERROR (Status);
 
+  XenBusEnumerateBus (Dev);
+
   Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
                              NotifyExitBoot,
                              (VOID*) Dev,
@@ -376,6 +395,9 @@ XenBusDxeDriverBindingStart (
 
 ErrorAllocated:
   FreePool (Dev);
+  gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid,
+                      This->DriverBindingHandle, ControllerHandle);
+ErrorOpenningProtocol:
   gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
                       This->DriverBindingHandle, ControllerHandle);
   return Status;
@@ -416,12 +438,56 @@ XenBusDxeDriverBindingStop (
   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
   )
 {
+  UINTN Index;
+  XENBUS_PROTOCOL *XenBusIo;
+  XENBUS_PRIVATE_DATA *ChildData;
+  EFI_STATUS Status;
   XENBUS_DEVICE *Dev = mMyDevice;
 
+  for (Index = 0; Index < NumberOfChildren; Index++) {
+    Status = gBS->OpenProtocol (
+               ChildHandleBuffer[Index],
+               &gXenBusProtocolGuid,
+               (VOID **) &XenBusIo,
+               This->DriverBindingHandle,
+               ControllerHandle,
+               EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "XenBusDxe: get children protocol failed: %r\n", Status));
+      continue;
+    }
+    ChildData = XENBUS_PRIVATE_DATA_FROM_THIS (XenBusIo);
+    Status = gBS->DisconnectController (ChildData->Handle, NULL, NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "XenBusDxe: error disconnecting child: %r\n",
+              Status));
+      continue;
+    }
+
+    Status = gBS->UninstallMultipleProtocolInterfaces (
+               ChildData->Handle,
+               &gEfiDevicePathProtocolGuid, ChildData->DevicePath,
+               &gXenBusProtocolGuid, &ChildData->XenBusIo,
+               NULL);
+    ASSERT_EFI_ERROR (Status);
+
+    FreePool ((VOID*)ChildData->XenBusIo.Type);
+    FreePool ((VOID*)ChildData->XenBusIo.Node);
+    FreePool ((VOID*)ChildData->XenBusIo.Backend);
+    FreePool (ChildData->DevicePath);
+    RemoveEntryList (&ChildData->Link);
+    FreePool (ChildData);
+  }
+  if (NumberOfChildren > 0) {
+    return EFI_SUCCESS;
+  }
+
   gBS->CloseEvent (Dev->ExitBootEvent);
   XenStoreDeinit (Dev);
   XenGrantTableDeinit (Dev);
 
+  gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid,
+         This->DriverBindingHandle, ControllerHandle);
   gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
          This->DriverBindingHandle, ControllerHandle);
 
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h
index 9f89c94..187f64c 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -98,6 +98,7 @@ extern EFI_COMPONENT_NAME_PROTOCOL  gXenBusDxeComponentName;
 #define PCI_DEVICE_ID_XEN_PLATFORM       0x0001
 
 
+typedef struct _XENBUS_DEVICE_PATH XENBUS_DEVICE_PATH;
 typedef struct _XENBUS_DEVICE XENBUS_DEVICE;
 
 // Have the state of the driver.
@@ -108,11 +109,29 @@ struct _XENBUS_DEVICE {
   EFI_HANDLE                    ControllerHandle;
   EFI_PCI_IO_PROTOCOL           *PciIo;
   EFI_EVENT                     ExitBootEvent;
+  EFI_DEVICE_PATH_PROTOCOL      *DevicePath;
+  LIST_ENTRY                    ChildList;
 
   VOID                          *Hyperpage;
   shared_info_t                 *SharedInfo;
 };
 
+// There is one of this struct allocated for every child.
+#define XENBUS_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('X', 'B', 'p', 'd')
+typedef struct {
+    UINTN Signature;
+    LIST_ENTRY Link;
+    EFI_HANDLE Handle;
+    XENBUS_PROTOCOL XenBusIo;
+    XENBUS_DEVICE *Dev;
+    XENBUS_DEVICE_PATH *DevicePath;
+} XENBUS_PRIVATE_DATA;
+
+#define XENBUS_PRIVATE_DATA_FROM_THIS(a) \
+  CR (a, XENBUS_PRIVATE_DATA, XenBusIo, XENBUS_PRIVATE_DATA_SIGNATURE)
+#define XENBUS_PRIVATE_DATA_FROM_LINK(a) \
+  CR (a, XENBUS_PRIVATE_DATA, Link, XENBUS_PRIVATE_DATA_SIGNATURE)
+
 /*
  * Helpers
  */
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
index 8e2466e..66f0356 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -41,6 +41,9 @@
   EventChannel.h
   XenStore.c
   XenStore.h
+  XenBus.c
+  XenBus.h
+  Helpers.c
 
 [Sources.IA32]
   Ia32/hypercall.S
-- 
Anthony PERARD

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

* [PATCH v3 16/19] OvmfPkg/XenBusDxe: Add Event Channel into XenBus protocol.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (14 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce XenBus support itself Anthony PERARD
@ 2014-10-17 17:03 ` Anthony PERARD
  2014-10-17 17:04 ` [PATCH v3 17/19] OvmfPkg/XenPvBlkDxe: Xen PV Block device, initial skeleton Anthony PERARD
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:03 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

This patch adds three event channel related functions:
- EventChannelAllocate: Allocate an event channel port that can be bind
  from a specified domain.
- EventChannelNotify: Send an event to the remote end of a channel.
- EventChannelClose: Close a local event channel port.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- eventchannel, update protocol to return error code.
- expand patch description
- Add comments in the XenBus Protocol header.

Change in V2:
- coding style
- adding comment to functions
- Rename Xenbus to XenBus.
---
 OvmfPkg/Include/Protocol/XenBus.h | 53 +++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/EventChannel.c  | 55 +++++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/EventChannel.h  | 52 ++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenBusDxe/XenBus.c        |  3 +++
 4 files changed, 163 insertions(+)

diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h
index e54077d..c85c928 100644
--- a/OvmfPkg/Include/Protocol/XenBus.h
+++ b/OvmfPkg/Include/Protocol/XenBus.h
@@ -79,6 +79,7 @@ typedef enum {
 
 
 #include <IndustryStandard/Xen/grant_table.h>
+#include <IndustryStandard/Xen/event_channel.h>
 
 ///
 /// Function prototypes
@@ -266,6 +267,54 @@ EFI_STATUS
   );
 
 /**
+  Allocate a port that can be bind from domain DomainId.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param DomainId   The domain ID that can bind the newly allocated port.
+  @param Port       A pointer to a evtchn_port_t that will contain the newly
+                    allocated port.
+
+  @retval UINT32    The return value from the hypercall, 0 if success.
+**/
+typedef
+UINT32
+(EFIAPI *XENBUS_EVENT_CHANNEL_ALLOCATE) (
+  IN  XENBUS_PROTOCOL *This,
+  IN  domid_t         DomainId,
+  OUT evtchn_port_t   *Port
+  );
+
+/**
+  Send an event to the remote end of the channel whose local endpoint is Port.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param Port       Local port to the the event from.
+
+  @retval UINT32    The return value from the hypercall, 0 if success.
+**/
+typedef
+UINT32
+(EFIAPI *XENBUS_EVENT_CHANNEL_NOTIFY) (
+  IN XENBUS_PROTOCOL  *This,
+  IN evtchn_port_t    Port
+  );
+
+/**
+  Close a local event channel Port.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param Port       The event channel to close.
+
+  @retval UINT32    The return value from the hypercall, 0 if success.
+**/
+typedef
+UINT32
+(EFIAPI *XENBUS_EVENT_CHANNEL_CLOSE) (
+  IN XENBUS_PROTOCOL  *This,
+  IN evtchn_port_t    Port
+  );
+
+/**
   Register a XenStore watch.
 
   XenStore watches allow a client to wait for changes to an object in the
@@ -361,6 +410,10 @@ struct _XENBUS_PROTOCOL {
   XENBUS_GRANT_ACCESS           GrantAccess;
   XENBUS_GRANT_END_ACCESS       GrantEndAccess;
 
+  XENBUS_EVENT_CHANNEL_ALLOCATE EventChannelAllocate;
+  XENBUS_EVENT_CHANNEL_NOTIFY   EventChannelNotify;
+  XENBUS_EVENT_CHANNEL_CLOSE    EventChannelClose;
+
   XENBUS_REGISTER_WATCH         RegisterWatch;
   XENBUS_REGISTER_WATCH_BACKEND RegisterWatchBackend;
   XENBUS_UNREGISTER_WATCH       UnregisterWatch;
diff --git a/OvmfPkg/XenBusDxe/EventChannel.c b/OvmfPkg/XenBusDxe/EventChannel.c
index 53d43db..e782e1c 100644
--- a/OvmfPkg/XenBusDxe/EventChannel.c
+++ b/OvmfPkg/XenBusDxe/EventChannel.c
@@ -47,3 +47,58 @@ XenEventChannelNotify (
   ReturnCode = XenHypercallEventChannelOp (Dev, EVTCHNOP_send, &Send);
   return ReturnCode;
 }
+
+UINT32
+EFIAPI
+XenBusEventChannelAllocate (
+  IN  XENBUS_PROTOCOL *This,
+  IN  domid_t         DomainId,
+  OUT evtchn_port_t   *Port
+  )
+{
+  XENBUS_PRIVATE_DATA *Private;
+  evtchn_alloc_unbound_t Parameter;
+  UINT32 ReturnCode;
+
+  Private = XENBUS_PRIVATE_DATA_FROM_THIS (This);
+
+  Parameter.dom = DOMID_SELF;
+  Parameter.remote_dom = DomainId;
+  ReturnCode = XenHypercallEventChannelOp (Private->Dev,
+                                   EVTCHNOP_alloc_unbound,
+                                   &Parameter);
+  if (ReturnCode != 0) {
+    DEBUG ((EFI_D_ERROR, "ERROR: alloc_unbound failed with rc=%d", ReturnCode));
+    return ReturnCode;
+  }
+  *Port = Parameter.port;
+  return ReturnCode;
+}
+
+UINT32
+EFIAPI
+XenBusEventChannelNotify (
+  IN XENBUS_PROTOCOL *This,
+  IN evtchn_port_t   Port
+  )
+{
+  XENBUS_PRIVATE_DATA *Private;
+
+  Private = XENBUS_PRIVATE_DATA_FROM_THIS(This);
+  return XenEventChannelNotify (Private->Dev, Port);
+}
+
+UINT32
+EFIAPI
+XenBusEventChannelClose (
+  IN XENBUS_PROTOCOL *This,
+  IN evtchn_port_t   Port
+  )
+{
+  XENBUS_PRIVATE_DATA *Private;
+  evtchn_close_t Close;
+
+  Private = XENBUS_PRIVATE_DATA_FROM_THIS (This);
+  Close.port = Port;
+  return XenHypercallEventChannelOp (Private->Dev, EVTCHNOP_close, &Close);
+}
diff --git a/OvmfPkg/XenBusDxe/EventChannel.h b/OvmfPkg/XenBusDxe/EventChannel.h
index 5cbe43b..4df922f 100644
--- a/OvmfPkg/XenBusDxe/EventChannel.h
+++ b/OvmfPkg/XenBusDxe/EventChannel.h
@@ -49,4 +49,56 @@ XenEventChannelNotify (
   IN evtchn_port_t Port
   );
 
+/*
+ * XenBus protocol
+ */
+
+/**
+  Allocate a port that can be bind from domain DomainId.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param DomainId   The domain ID that can bind the newly allocated port.
+  @param Port       A pointer to a evtchn_port_t that will contain the newly
+                    allocated port.
+
+  @retval UINT32    The return value from the hypercall, 0 if success.
+**/
+UINT32
+EFIAPI
+XenBusEventChannelAllocate (
+  IN  XENBUS_PROTOCOL *This,
+  IN  domid_t         DomainId,
+  OUT evtchn_port_t   *Port
+  );
+
+/**
+  Send an event to the remote end of the channel whose local endpoint is Port.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param Port       Local port to the the event from.
+
+  @retval UINT32    The return value from the hypercall, 0 if success.
+**/
+UINT32
+EFIAPI
+XenBusEventChannelNotify (
+  IN XENBUS_PROTOCOL *This,
+  IN evtchn_port_t   Port
+  );
+
+/**
+  Close a local event channel Port.
+
+  @param This       A pointer to the XENBUS_PROTOCOL.
+  @param Port       The event channel to close.
+
+  @retval UINT32    The return value from the hypercall, 0 if success.
+**/
+UINT32
+EFIAPI
+XenBusEventChannelClose (
+  IN XENBUS_PROTOCOL *This,
+  IN evtchn_port_t   Port
+  );
+
 #endif
diff --git a/OvmfPkg/XenBusDxe/XenBus.c b/OvmfPkg/XenBusDxe/XenBus.c
index e595767..9ac654d 100644
--- a/OvmfPkg/XenBusDxe/XenBus.c
+++ b/OvmfPkg/XenBusDxe/XenBus.c
@@ -359,6 +359,9 @@ STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = {
   .XenBusIo.SetState = XenBusSetState,
   .XenBusIo.GrantAccess = XenBusGrantAccess,
   .XenBusIo.GrantEndAccess = XenBusGrantEndAccess,
+  .XenBusIo.EventChannelAllocate = XenBusEventChannelAllocate,
+  .XenBusIo.EventChannelNotify = XenBusEventChannelNotify,
+  .XenBusIo.EventChannelClose = XenBusEventChannelClose,
   .XenBusIo.RegisterWatch = XenBusRegisterWatch,
   .XenBusIo.RegisterWatchBackend = XenBusRegisterWatchBackend,
   .XenBusIo.UnregisterWatch = XenBusUnregisterWatch,
-- 
Anthony PERARD

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

* [PATCH v3 17/19] OvmfPkg/XenPvBlkDxe: Xen PV Block device, initial skeleton
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (15 preceding siblings ...)
  2014-10-17 17:03 ` [PATCH v3 16/19] OvmfPkg/XenBusDxe: Add Event Channel into XenBus protocol Anthony PERARD
@ 2014-10-17 17:04 ` Anthony PERARD
  2014-10-17 17:04 ` [PATCH v3 18/19] OvmfPkg/XenPvBlkDxe: Add BlockFront client Anthony PERARD
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:04 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

A ParaVirtualize block driver.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- enable compilation for Ia32 and Ia32X64
- fix version (driver binding)

Change in V2:
- Add minimal support for controller name
- Remove stuff about BlockIo2
- Little cleanup
- Licenses and file headers
- Rename XenbusIo into XenBusIo
---
 OvmfPkg/OvmfPkgIa32.dsc             |   1 +
 OvmfPkg/OvmfPkgIa32.fdf             |   1 +
 OvmfPkg/OvmfPkgIa32X64.dsc          |   1 +
 OvmfPkg/OvmfPkgIa32X64.fdf          |   1 +
 OvmfPkg/OvmfPkgX64.dsc              |   1 +
 OvmfPkg/OvmfPkgX64.fdf              |   1 +
 OvmfPkg/XenPvBlkDxe/ComponentName.c | 192 +++++++++++++++++++++
 OvmfPkg/XenPvBlkDxe/ComponentName.h | 110 ++++++++++++
 OvmfPkg/XenPvBlkDxe/DriverBinding.h | 159 +++++++++++++++++
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c   | 332 ++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h   |  98 +++++++++++
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf |  76 +++++++++
 12 files changed, 973 insertions(+)
 create mode 100644 OvmfPkg/XenPvBlkDxe/ComponentName.c
 create mode 100644 OvmfPkg/XenPvBlkDxe/ComponentName.h
 create mode 100644 OvmfPkg/XenPvBlkDxe/DriverBinding.h
 create mode 100644 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
 create mode 100644 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
 create mode 100644 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index c16aea2..baed129 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -429,6 +429,7 @@
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
   OvmfPkg/XenBusDxe/XenBusDxe.inf
+  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
     <LibraryClasses>
       PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 0b75fd2..932aefa 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -228,6 +228,7 @@ INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
 INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
+INF  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 340ef00..32993cc 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -436,6 +436,7 @@
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
   OvmfPkg/XenBusDxe/XenBusDxe.inf
+  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
     <LibraryClasses>
       PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 146e57f..048d8bf 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -228,6 +228,7 @@ INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
 INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
+INF  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 74c799c..736a549 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -434,6 +434,7 @@
   OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
   OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
   OvmfPkg/XenBusDxe/XenBusDxe.inf
+  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
   OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
     <LibraryClasses>
       PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 8b6a80b..bcf0b9d 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -228,6 +228,7 @@ INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
 INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
 INF  OvmfPkg/XenBusDxe/XenBusDxe.inf
+INF  OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
 
 !if $(SECURE_BOOT_ENABLE) == TRUE
   INF  SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
diff --git a/OvmfPkg/XenPvBlkDxe/ComponentName.c b/OvmfPkg/XenPvBlkDxe/ComponentName.c
new file mode 100644
index 0000000..4243e24
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/ComponentName.c
@@ -0,0 +1,192 @@
+/** @file
+  Component Name functions implementation for XenPvBlk driver.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "XenPvBlkDxe.h"
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL  gXenPvBlkDxeComponentName = {
+  (EFI_COMPONENT_NAME_GET_DRIVER_NAME)    XenPvBlkDxeComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)XenPvBlkDxeComponentNameGetControllerName,
+  "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL  gXenPvBlkDxeComponentName2 = {
+  XenPvBlkDxeComponentNameGetDriverName,
+  XenPvBlkDxeComponentNameGetControllerName,
+  "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mXenPvBlkDxeDriverNameTable[] = {
+  { "eng;en", (CHAR16 *)L"Xen PV Block Driver" },
+  { NULL, NULL }
+};
+
+///
+/// Table of controller names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mXenPvBlkDxeControllerNameTable[] = {
+  { "eng;en", (CHAR16 *)L"Xen PV Block Device" },
+  { NULL, NULL }
+};
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that that the caller
+                     is requesting, and it must match one of the languages specified
+                     in SupportedLanguages.  The number of languages supported by a
+                     driver is up to the driver writer.
+  @param  DriverName A pointer to the Unicode string to return.  This Unicode string
+                     is the name of the driver specified by This in the language
+                     specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This
+                                and the language specified by Language was returned
+                                in DriverName.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mXenPvBlkDxeDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This != &gXenPvBlkDxeComponentName2)
+           );
+}
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle The handle of a controller that the driver specified by
+                           This is managing.  This handle specifies the controller
+                           whose name is to be returned.
+  @param  ChildHandle      The handle of the child controller to retrieve the name
+                           of.  This is an optional parameter that may be NULL.  It
+                           will be NULL for device drivers.  It will also be NULL
+                           for a bus drivers that wish to retrieve the name of the
+                           bus controller.  It will not be NULL for a bus driver
+                           that wishes to retrieve the name of a child controller.
+  @param  Language         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller name
+                           that the caller is requesting, and it must match one
+                           of the languages specified in SupportedLanguages.  The
+                           number of languages supported by a driver is up to the
+                           driver writer.
+  @param  ControllerName   A pointer to the Unicode string to return.  This Unicode
+                           string is the name of the controller specified by
+                           ControllerHandle and ChildHandle in the language specified
+                           by Language, from the point of view of the driver specified
+                           by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user-readable name in the
+                                language specified by Language for the driver
+                                specified by This was returned in DriverName.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently managing
+                                the controller specified by ControllerHandle and
+                                ChildHandle.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // ChildHandle must be NULL for a Device Driver
+  //
+  if (ChildHandle != NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Make sure this driver is currently managing ControllerHandle
+  //
+  Status = EfiTestManagedDevice (
+             ControllerHandle,
+             gXenPvBlkDxeDriverBinding.DriverBindingHandle,
+             &gXenBusProtocolGuid
+             );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Lookup name of controller specified by ControllerHandle
+  //
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mXenPvBlkDxeControllerNameTable,
+           ControllerName,
+           (BOOLEAN)(This != &gXenPvBlkDxeComponentName2)
+           );
+}
diff --git a/OvmfPkg/XenPvBlkDxe/ComponentName.h b/OvmfPkg/XenPvBlkDxe/ComponentName.h
new file mode 100644
index 0000000..9087263
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/ComponentName.h
@@ -0,0 +1,110 @@
+/** @file
+  Component Name functions declaration for XenPvBlk driver.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+/**
+  Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+  @param  This       A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  Language   A pointer to a three-character ISO 639-2 language identifier.
+                     This is the language of the driver name that that the caller
+                     is requesting, and it must match one of the languages specified
+                     in SupportedLanguages.  The number of languages supported by a
+                     driver is up to the driver writer.
+  @param  DriverName A pointer to the Unicode string to return.  This Unicode string
+                     is the name of the driver specified by This in the language
+                     specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by This
+                                and the language specified by Language was returned
+                                in DriverName.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeComponentNameGetDriverName (
+  IN EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by an EFI Driver.
+
+  @param  This             A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+  @param  ControllerHandle The handle of a controller that the driver specified by
+                           This is managing.  This handle specifies the controller
+                           whose name is to be returned.
+  @param  ChildHandle      The handle of the child controller to retrieve the name
+                           of.  This is an optional parameter that may be NULL.  It
+                           will be NULL for device drivers.  It will also be NULL
+                           for a bus drivers that wish to retrieve the name of the
+                           bus controller.  It will not be NULL for a bus driver
+                           that wishes to retrieve the name of a child controller.
+  @param  Language         A pointer to a three character ISO 639-2 language
+                           identifier.  This is the language of the controller name
+                           that the caller is requesting, and it must match one
+                           of the languages specified in SupportedLanguages.  The
+                           number of languages supported by a driver is up to the
+                           driver writer.
+  @param  ControllerName   A pointer to the Unicode string to return.  This Unicode
+                           string is the name of the controller specified by
+                           ControllerHandle and ChildHandle in the language specified
+                           by Language, from the point of view of the driver specified
+                           by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user-readable name in the
+                                language specified by Language for the driver
+                                specified by This was returned in DriverName.
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently managing
+                                the controller specified by ControllerHandle and
+                                ChildHandle.
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support the
+                                language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
+  IN  EFI_HANDLE                    ControllerHandle,
+  IN  EFI_HANDLE                    ChildHandle        OPTIONAL,
+  IN  CHAR8                         *Language,
+  OUT CHAR16                        **ControllerName
+  );
diff --git a/OvmfPkg/XenPvBlkDxe/DriverBinding.h b/OvmfPkg/XenPvBlkDxe/DriverBinding.h
new file mode 100644
index 0000000..e819257
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/DriverBinding.h
@@ -0,0 +1,159 @@
+
+/** @file
+  Driver Binding functions declaration for XenPvBlk driver.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+/**
+  Tests to see if this driver supports a given controller. If a child device is provided,
+  it further tests to see if this driver supports creating a handle for the specified child device.
+
+  This function checks to see if the driver specified by This supports the device specified by
+  ControllerHandle. Drivers will typically use the device path attached to
+  ControllerHandle and/or the services from the bus I/O abstraction attached to
+  ControllerHandle to determine if the driver supports ControllerHandle. This function
+  may be called many times during platform initialization. In order to reduce boot times, the tests
+  performed by this function must be very small, and take as little time as possible to execute. This
+  function must not change the state of any hardware devices, and this function must be aware that the
+  device specified by ControllerHandle may already be managed by the same driver or a
+  different driver. This function must match its calls to AllocatePages() with FreePages(),
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+  Because ControllerHandle may have been previously started by the same driver, if a protocol is
+  already in the opened state, then it must not be closed with CloseProtocol(). This is required
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For bus drivers, if this parameter is not NULL, then
+                                   the bus driver must determine if the bus controller specified
+                                   by ControllerHandle and the child controller specified
+                                   by RemainingDevicePath are both supported by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by a different
+                                   driver or an application that requires exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service ConnectController().
+  As a result, much of the error checking on the parameters to Start() has been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver specified by This must
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For a bus driver, if this parameter is NULL, then handles
+                                   for all the children of Controller are created by this driver.
+                                   If this parameter is not NULL and the first Device Path Node is
+                                   not the End of Device Path Node, then only the handle for the
+                                   child device specified by the first Device Path Node of
+                                   RemainingDevicePath is created by this driver.
+                                   If the first Device Path Node of RemainingDevicePath is
+                                   the End of Device Path Node, no child handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  );
+
+/**
+  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been moved
+  into this common boot service. It is legal to call Stop() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+     Start() function, and the Start() function must have called OpenProtocol() on
+     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
+                                support a bus specific I/O protocol for the driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                  ControllerHandle,
+  IN  UINTN                       NumberOfChildren,
+  IN  EFI_HANDLE                  *ChildHandleBuffer OPTIONAL
+  );
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
new file mode 100644
index 0000000..ad45e69
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
@@ -0,0 +1,332 @@
+/** @file
+  This driver produce a BlockIo protocol instance for a Xen PV block device.
+
+  This driver support XenBus protocol of type 'vbd'. Every function that
+  comsume XenBus protocol are in BlockFront, which the implementation to access
+  a Xen PV device. The BlockIo implementation is in it's one file and will call
+  BlockFront functions.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "XenPvBlkDxe.h"
+
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gXenPvBlkDxeDriverBinding = {
+  XenPvBlkDxeDriverBindingSupported,
+  XenPvBlkDxeDriverBindingStart,
+  XenPvBlkDxeDriverBindingStop,
+  XEN_PV_BLK_DXE_VERSION,
+  NULL,
+  NULL
+};
+
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS  Status;
+
+  EFI_HANDLE  *HandleBuffer;
+  UINTN       HandleCount;
+  UINTN       Index;
+
+
+  //
+  // Retrieve array of all handles in the handle database
+  //
+  Status = gBS->LocateHandleBuffer (
+                  AllHandles,
+                  NULL,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Disconnect the current driver from handles in the handle database
+  //
+  for (Index = 0; Index < HandleCount; Index++) {
+    gBS->DisconnectController (HandleBuffer[Index], gImageHandle, NULL);
+  }
+
+  //
+  // Free the array of handles
+  //
+  FreePool (HandleBuffer);
+
+
+  //
+  // Uninstall protocols installed in the driver entry point
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  ImageHandle,
+                  &gEfiDriverBindingProtocolGuid, &gXenPvBlkDxeDriverBinding,
+                  &gEfiComponentNameProtocolGuid,  &gXenPvBlkDxeComponentName,
+                  &gEfiComponentName2ProtocolGuid, &gXenPvBlkDxeComponentName2,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Install UEFI Driver Model protocol(s).
+  //
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gXenPvBlkDxeDriverBinding,
+             ImageHandle,
+             &gXenPvBlkDxeComponentName,
+             &gXenPvBlkDxeComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+
+/**
+  Tests to see if this driver supports a given controller. If a child device is provided,
+  it further tests to see if this driver supports creating a handle for the specified child device.
+
+  This function checks to see if the driver specified by This supports the device specified by
+  ControllerHandle. Drivers will typically use the device path attached to
+  ControllerHandle and/or the services from the bus I/O abstraction attached to
+  ControllerHandle to determine if the driver supports ControllerHandle. This function
+  may be called many times during platform initialization. In order to reduce boot times, the tests
+  performed by this function must be very small, and take as little time as possible to execute. This
+  function must not change the state of any hardware devices, and this function must be aware that the
+  device specified by ControllerHandle may already be managed by the same driver or a
+  different driver. This function must match its calls to AllocatePages() with FreePages(),
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+  Because ControllerHandle may have been previously started by the same driver, if a protocol is
+  already in the opened state, then it must not be closed with CloseProtocol(). This is required
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For bus drivers, if this parameter is not NULL, then
+                                   the bus driver must determine if the bus controller specified
+                                   by ControllerHandle and the child controller specified
+                                   by RemainingDevicePath are both supported by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by a different
+                                   driver or an application that requires exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeDriverBindingSupported (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS Status;
+  XENBUS_PROTOCOL *XenBusIo;
+
+  Status = gBS->OpenProtocol (
+                ControllerHandle,
+                &gXenBusProtocolGuid,
+                (VOID **)&XenBusIo,
+                This->DriverBindingHandle,
+                ControllerHandle,
+                EFI_OPEN_PROTOCOL_BY_DRIVER
+                );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  if (AsciiStrCmp (XenBusIo->Type, "vbd") == 0) {
+    Status = EFI_SUCCESS;
+  } else {
+    Status = EFI_UNSUPPORTED;
+  }
+
+  gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
+                      This->DriverBindingHandle, ControllerHandle);
+
+  return Status;
+}
+
+/**
+  Starts a device controller.
+
+  The Start() function is designed to be invoked from the EFI boot service ConnectController().
+  As a result, much of the error checking on the parameters to Start() has been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver specified by This must
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For a bus driver, if this parameter is NULL, then handles
+                                   for all the children of Controller are created by this driver.
+                                   If this parameter is not NULL and the first Device Path Node is
+                                   not the End of Device Path Node, then only the handle for the
+                                   child device specified by the first Device Path Node of
+                                   RemainingDevicePath is created by this driver.
+                                   If the first Device Path Node of RemainingDevicePath is
+                                   the End of Device Path Node, no child handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeDriverBindingStart (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
+  )
+{
+  EFI_STATUS Status;
+  XENBUS_PROTOCOL *XenBusIo;
+
+  Status = gBS->OpenProtocol (
+                ControllerHandle,
+                &gXenBusProtocolGuid,
+                (VOID **)&XenBusIo,
+                This->DriverBindingHandle,
+                ControllerHandle,
+                EFI_OPEN_PROTOCOL_BY_DRIVER
+                );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Stops a device controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been moved
+  into this common boot service. It is legal to call Stop() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+     Start() function, and the Start() function must have called OpenProtocol() on
+     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
+                                support a bus specific I/O protocol for the driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeDriverBindingStop (
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                   ControllerHandle,
+  IN UINTN                        NumberOfChildren,
+  IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
+  )
+{
+  gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
+         This->DriverBindingHandle, ControllerHandle);
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
new file mode 100644
index 0000000..5351a96
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
@@ -0,0 +1,98 @@
+/** @file
+  Main header for XenPvBlkDxe
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#ifndef __EFI_XEN_PV_BLK_DXE_H__
+#define __EFI_XEN_PV_BLK_DXE_H__
+
+#include <Uefi.h>
+
+//
+// Xen interface version used
+//
+#define __XEN_INTERFACE_VERSION__ 0x00040400
+#define xen_mb() MemoryFence()
+#define xen_rmb() MemoryFence()
+#define xen_wmb() MemoryFence()
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DebugLib.h>
+
+
+//
+// UEFI Driver Model Protocols
+//
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/ComponentName.h>
+
+
+//
+// Consumed Protocols
+//
+#include <Protocol/XenBus.h>
+
+
+//
+// Produced Protocols
+//
+#include <Protocol/BlockIo.h>
+
+
+//
+// Driver Version
+//
+#define XEN_PV_BLK_DXE_VERSION  0x00000010
+
+
+//
+// Protocol instances
+//
+extern EFI_DRIVER_BINDING_PROTOCOL  gXenPvBlkDxeDriverBinding;
+extern EFI_COMPONENT_NAME2_PROTOCOL  gXenPvBlkDxeComponentName2;
+extern EFI_COMPONENT_NAME_PROTOCOL  gXenPvBlkDxeComponentName;
+
+
+//
+// Include files with function prototypes
+//
+#include "DriverBinding.h"
+#include "ComponentName.h"
+
+
+#endif
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
new file mode 100644
index 0000000..4103996
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
@@ -0,0 +1,76 @@
+
+## @file
+#  TODO: Brief Description of UEFI Driver XenPvBlkDxe
+#
+#  Copyright (C) 2014, Citrix Ltd.
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions
+#  are met:
+#
+#  * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#  * Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+#  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+#  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+#  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+#  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+#  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+#  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+#  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+#  POSSIBILITY OF SUCH DAMAGE.
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = XenPvBlkDxe
+  FILE_GUID                 = 8c2487ea-9af3-11e3-b966-b8ac6f7d65e6
+  MODULE_TYPE               = UEFI_DRIVER
+
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = XenPvBlkDxeDriverEntryPoint
+  UNLOAD_IMAGE              = XenPvBlkDxeUnload
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[Sources]
+  XenPvBlkDxe.h
+  XenPvBlkDxe.c
+  ComponentName.c
+  ComponentName.h
+
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  DevicePathLib
+  DebugLib
+
+
+[Protocols]
+  gEfiDriverBindingProtocolGuid
+  gEfiBlockIoProtocolGuid
+  gEfiComponentName2ProtocolGuid
+  gEfiComponentNameProtocolGuid
+  gXenBusProtocolGuid
+  gEfiDevicePathProtocolGuid                    ## TO_START
+
+
+[Guids]
+
-- 
Anthony PERARD

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

* [PATCH v3 18/19] OvmfPkg/XenPvBlkDxe: Add BlockFront client.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (16 preceding siblings ...)
  2014-10-17 17:04 ` [PATCH v3 17/19] OvmfPkg/XenPvBlkDxe: Xen PV Block device, initial skeleton Anthony PERARD
@ 2014-10-17 17:04 ` Anthony PERARD
  2014-10-17 17:04 ` [PATCH v3 19/19] OvmfPkg/XenPvBlkDxe: Add BlockIo Anthony PERARD
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:04 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Samuel Thibault, Xen Devel

This is the code that will do the actual communication between OVMF and
a PV block backend, where the block device lives. The protocol used is
describe in the blkif.h header.

This implementation originally comes from Mini-OS, a part of the Xen
Project.

License: This patch adds some files which are under the MIT license.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- Improve comment of XenBusReadUint64.
- Moving blkif.h to this patch
  with the necessary #pragma pack(4) applied for Ia32.
- Add a note about the license in the commit message
- Add "The protocol used is describe in the blkif.h header." in the
  commit message
- Have a mandatory sector-size multiple of 512 or fail to initialize.
- use Sector instead of Offset for IO request.
  with Sector been 512-byte unit.
- print something if EventChannelNotify return an error.

Change in V2:
- trigger CoW is probably not needed on OVMF (as opposed to Mini-OS),
  removed the test.
- comments
- renamed XenbusReadInteger to XenBusReadUint64
- remove callback from IoData, use simple status instead
- return a status from the synchronus io
- Close protocol if blockfront init fail.
- fix few debug print
- Rename XenbusIo to XenBusIo
- XenPvBlkWaitForBackendState will return an error if the new backend
  states is not the expected state.
- Add the license
---
 OvmfPkg/Include/IndustryStandard/Xen/io/blkif.h | 619 +++++++++++++++++++++++
 OvmfPkg/XenPvBlkDxe/BlockFront.c                | 647 ++++++++++++++++++++++++
 OvmfPkg/XenPvBlkDxe/BlockFront.h                |  87 ++++
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c               |  13 +
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf             |   2 +
 5 files changed, 1368 insertions(+)
 create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/blkif.h
 create mode 100644 OvmfPkg/XenPvBlkDxe/BlockFront.c
 create mode 100644 OvmfPkg/XenPvBlkDxe/BlockFront.h

diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/blkif.h b/OvmfPkg/Include/IndustryStandard/Xen/io/blkif.h
new file mode 100644
index 0000000..2cfc1ab
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Xen/io/blkif.h
@@ -0,0 +1,619 @@
+/******************************************************************************
+ * blkif.h
+ *
+ * Unified block-device I/O interface for Xen guest OSes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2003-2004, Keir Fraser
+ * Copyright (c) 2012, Spectra Logic Corporation
+ */
+
+#ifndef __XEN_PUBLIC_IO_BLKIF_H__
+#define __XEN_PUBLIC_IO_BLKIF_H__
+
+#include "ring.h"
+#include "../grant_table.h"
+
+/*
+ * Front->back notifications: When enqueuing a new request, sending a
+ * notification can be made conditional on req_event (i.e., the generic
+ * hold-off mechanism provided by the ring macros). Backends must set
+ * req_event appropriately (e.g., using RING_FINAL_CHECK_FOR_REQUESTS()).
+ *
+ * Back->front notifications: When enqueuing a new response, sending a
+ * notification can be made conditional on rsp_event (i.e., the generic
+ * hold-off mechanism provided by the ring macros). Frontends must set
+ * rsp_event appropriately (e.g., using RING_FINAL_CHECK_FOR_RESPONSES()).
+ */
+
+#ifndef blkif_vdev_t
+#define blkif_vdev_t   UINT16
+#endif
+#define blkif_sector_t UINT64
+
+/*
+ * Feature and Parameter Negotiation
+ * =================================
+ * The two halves of a Xen block driver utilize nodes within the XenStore to
+ * communicate capabilities and to negotiate operating parameters.  This
+ * section enumerates these nodes which reside in the respective front and
+ * backend portions of the XenStore, following the XenBus convention.
+ *
+ * All data in the XenStore is stored as strings.  Nodes specifying numeric
+ * values are encoded in decimal.  Integer value ranges listed below are
+ * expressed as fixed sized integer types capable of storing the conversion
+ * of a properly formated node string, without loss of information.
+ *
+ * Any specified default value is in effect if the corresponding XenBus node
+ * is not present in the XenStore.
+ *
+ * XenStore nodes in sections marked "PRIVATE" are solely for use by the
+ * driver side whose XenBus tree contains them.
+ *
+ * XenStore nodes marked "DEPRECATED" in their notes section should only be
+ * used to provide interoperability with legacy implementations.
+ *
+ * See the XenBus state transition diagram below for details on when XenBus
+ * nodes must be published and when they can be queried.
+ *
+ *****************************************************************************
+ *                            Backend XenBus Nodes
+ *****************************************************************************
+ *
+ *------------------ Backend Device Identification (PRIVATE) ------------------
+ *
+ * mode
+ *      Values:         "r" (read only), "w" (writable)
+ *
+ *      The read or write access permissions to the backing store to be
+ *      granted to the frontend.
+ *
+ * params
+ *      Values:         string
+ *
+ *      A free formatted string providing sufficient information for the
+ *      backend driver to open the backing device.  (e.g. the path to the
+ *      file or block device representing the backing store.)
+ *
+ * type
+ *      Values:         "file", "phy", "tap"
+ *
+ *      The type of the backing device/object.
+ *
+ *--------------------------------- Features ---------------------------------
+ *
+ * feature-barrier
+ *      Values:         0/1 (boolean)
+ *      Default Value:  0
+ *
+ *      A value of "1" indicates that the backend can process requests
+ *      containing the BLKIF_OP_WRITE_BARRIER request opcode.  Requests
+ *      of this type may still be returned at any time with the
+ *      BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-flush-cache
+ *      Values:         0/1 (boolean)
+ *      Default Value:  0
+ *
+ *      A value of "1" indicates that the backend can process requests
+ *      containing the BLKIF_OP_FLUSH_DISKCACHE request opcode.  Requests
+ *      of this type may still be returned at any time with the
+ *      BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-discard
+ *      Values:         0/1 (boolean)
+ *      Default Value:  0
+ *
+ *      A value of "1" indicates that the backend can process requests
+ *      containing the BLKIF_OP_DISCARD request opcode.  Requests
+ *      of this type may still be returned at any time with the
+ *      BLKIF_RSP_EOPNOTSUPP result code.
+ *
+ * feature-persistent
+ *      Values:         0/1 (boolean)
+ *      Default Value:  0
+ *      Notes: 7
+ *
+ *      A value of "1" indicates that the backend can keep the grants used
+ *      by the frontend driver mapped, so the same set of grants should be
+ *      used in all transactions. The maximum number of grants the backend
+ *      can map persistently depends on the implementation, but ideally it
+ *      should be RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST. Using this
+ *      feature the backend doesn't need to unmap each grant, preventing
+ *      costly TLB flushes. The backend driver should only map grants
+ *      persistently if the frontend supports it. If a backend driver chooses
+ *      to use the persistent protocol when the frontend doesn't support it,
+ *      it will probably hit the maximum number of persistently mapped grants
+ *      (due to the fact that the frontend won't be reusing the same grants),
+ *      and fall back to non-persistent mode. Backend implementations may
+ *      shrink or expand the number of persistently mapped grants without
+ *      notifying the frontend depending on memory constraints (this might
+ *      cause a performance degradation).
+ *
+ *      If a backend driver wants to limit the maximum number of persistently
+ *      mapped grants to a value less than RING_SIZE *
+ *      BLKIF_MAX_SEGMENTS_PER_REQUEST a LRU strategy should be used to
+ *      discard the grants that are less commonly used. Using a LRU in the
+ *      backend driver paired with a LIFO queue in the frontend will
+ *      allow us to have better performance in this scenario.
+ *
+ *----------------------- Request Transport Parameters ------------------------
+ *
+ * max-ring-page-order
+ *      Values:         <UINT32>
+ *      Default Value:  0
+ *      Notes:          1, 3
+ *
+ *      The maximum supported size of the request ring buffer in units of
+ *      lb(machine pages). (e.g. 0 == 1 page,  1 = 2 pages, 2 == 4 pages,
+ *      etc.).
+ *
+ * max-ring-pages
+ *      Values:         <UINT32>
+ *      Default Value:  1
+ *      Notes:          DEPRECATED, 2, 3
+ *
+ *      The maximum supported size of the request ring buffer in units of
+ *      machine pages.  The value must be a power of 2.
+ *
+ *------------------------- Backend Device Properties -------------------------
+ *
+ * discard-alignment
+ *      Values:         <UINT32>
+ *      Default Value:  0
+ *      Notes:          4, 5
+ *
+ *      The offset, in bytes from the beginning of the virtual block device,
+ *      to the first, addressable, discard extent on the underlying device.
+ *
+ * discard-granularity
+ *      Values:         <UINT32>
+ *      Default Value:  <"sector-size">
+ *      Notes:          4
+ *
+ *      The size, in bytes, of the individually addressable discard extents
+ *      of the underlying device.
+ *
+ * discard-secure
+ *      Values:         0/1 (boolean)
+ *      Default Value:  0
+ *      Notes:          10
+ *
+ *      A value of "1" indicates that the backend can process BLKIF_OP_DISCARD
+ *      requests with the BLKIF_DISCARD_SECURE flag set.
+ *
+ * info
+ *      Values:         <UINT32> (bitmap)
+ *
+ *      A collection of bit flags describing attributes of the backing
+ *      device.  The VDISK_* macros define the meaning of each bit
+ *      location.
+ *
+ * sector-size
+ *      Values:         <UINT32>
+ *
+ *      The logical sector size, in bytes, of the backend device.
+ *
+ * physical-sector-size
+ *      Values:         <UINT32>
+ *
+ *      The physical sector size, in bytes, of the backend device.
+ *
+ * sectors
+ *      Values:         <UINT64>
+ *
+ *      The size of the backend device, expressed in units of its logical
+ *      sector size ("sector-size").
+ *
+ *****************************************************************************
+ *                            Frontend XenBus Nodes
+ *****************************************************************************
+ *
+ *----------------------- Request Transport Parameters -----------------------
+ *
+ * event-channel
+ *      Values:         <UINT32>
+ *
+ *      The identifier of the Xen event channel used to signal activity
+ *      in the ring buffer.
+ *
+ * ring-ref
+ *      Values:         <UINT32>
+ *      Notes:          6
+ *
+ *      The Xen grant reference granting permission for the backend to map
+ *      the sole page in a single page sized ring buffer.
+ *
+ * ring-ref%u
+ *      Values:         <UINT32>
+ *      Notes:          6
+ *
+ *      For a frontend providing a multi-page ring, a "number of ring pages"
+ *      sized list of nodes, each containing a Xen grant reference granting
+ *      permission for the backend to map the page of the ring located
+ *      at page index "%u".  Page indexes are zero based.
+ *
+ * protocol
+ *      Values:         string (XEN_IO_PROTO_ABI_*)
+ *      Default Value:  XEN_IO_PROTO_ABI_NATIVE
+ *
+ *      The machine ABI rules governing the format of all ring request and
+ *      response structures.
+ *
+ * ring-page-order
+ *      Values:         <UINT32>
+ *      Default Value:  0
+ *      Maximum Value:  MAX(ffs(max-ring-pages) - 1, max-ring-page-order)
+ *      Notes:          1, 3
+ *
+ *      The size of the frontend allocated request ring buffer in units
+ *      of lb(machine pages). (e.g. 0 == 1 page, 1 = 2 pages, 2 == 4 pages,
+ *      etc.).
+ *
+ * num-ring-pages
+ *      Values:         <UINT32>
+ *      Default Value:  1
+ *      Maximum Value:  MAX(max-ring-pages,(0x1 << max-ring-page-order))
+ *      Notes:          DEPRECATED, 2, 3
+ *
+ *      The size of the frontend allocated request ring buffer in units of
+ *      machine pages.  The value must be a power of 2.
+ *
+ * feature-persistent
+ *      Values:         0/1 (boolean)
+ *      Default Value:  0
+ *      Notes: 7, 8, 9
+ *
+ *      A value of "1" indicates that the frontend will reuse the same grants
+ *      for all transactions, allowing the backend to map them with write
+ *      access (even when it should be read-only). If the frontend hits the
+ *      maximum number of allowed persistently mapped grants, it can fallback
+ *      to non persistent mode. This will cause a performance degradation,
+ *      since the the backend driver will still try to map those grants
+ *      persistently. Since the persistent grants protocol is compatible with
+ *      the previous protocol, a frontend driver can choose to work in
+ *      persistent mode even when the backend doesn't support it.
+ *
+ *      It is recommended that the frontend driver stores the persistently
+ *      mapped grants in a LIFO queue, so a subset of all persistently mapped
+ *      grants gets used commonly. This is done in case the backend driver
+ *      decides to limit the maximum number of persistently mapped grants
+ *      to a value less than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *
+ *------------------------- Virtual Device Properties -------------------------
+ *
+ * device-type
+ *      Values:         "disk", "cdrom", "floppy", etc.
+ *
+ * virtual-device
+ *      Values:         <UINT32>
+ *
+ *      A value indicating the physical device to virtualize within the
+ *      frontend's domain.  (e.g. "The first ATA disk", "The third SCSI
+ *      disk", etc.)
+ *
+ *      See docs/misc/vbd-interface.txt for details on the format of this
+ *      value.
+ *
+ * Notes
+ * -----
+ * (1) Multi-page ring buffer scheme first developed in the Citrix XenServer
+ *     PV drivers.
+ * (2) Multi-page ring buffer scheme first used in some RedHat distributions
+ *     including a distribution deployed on certain nodes of the Amazon
+ *     EC2 cluster.
+ * (3) Support for multi-page ring buffers was implemented independently,
+ *     in slightly different forms, by both Citrix and RedHat/Amazon.
+ *     For full interoperability, block front and backends should publish
+ *     identical ring parameters, adjusted for unit differences, to the
+ *     XenStore nodes used in both schemes.
+ * (4) Devices that support discard functionality may internally allocate space
+ *     (discardable extents) in units that are larger than the exported logical
+ *     block size. If the backing device has such discardable extents the
+ *     backend should provide both discard-granularity and discard-alignment.
+ *     Providing just one of the two may be considered an error by the frontend.
+ *     Backends supporting discard should include discard-granularity and
+ *     discard-alignment even if it supports discarding individual sectors.
+ *     Frontends should assume discard-alignment == 0 and discard-granularity
+ *     == sector size if these keys are missing.
+ * (5) The discard-alignment parameter allows a physical device to be
+ *     partitioned into virtual devices that do not necessarily begin or
+ *     end on a discardable extent boundary.
+ * (6) When there is only a single page allocated to the request ring,
+ *     'ring-ref' is used to communicate the grant reference for this
+ *     page to the backend.  When using a multi-page ring, the 'ring-ref'
+ *     node is not created.  Instead 'ring-ref0' - 'ring-refN' are used.
+ * (7) When using persistent grants data has to be copied from/to the page
+ *     where the grant is currently mapped. The overhead of doing this copy
+ *     however doesn't suppress the speed improvement of not having to unmap
+ *     the grants.
+ * (8) The frontend driver has to allow the backend driver to map all grants
+ *     with write access, even when they should be mapped read-only, since
+ *     further requests may reuse these grants and require write permissions.
+ * (9) Linux implementation doesn't have a limit on the maximum number of
+ *     grants that can be persistently mapped in the frontend driver, but
+ *     due to the frontent driver implementation it should never be bigger
+ *     than RING_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST.
+ *(10) The discard-secure property may be present and will be set to 1 if the
+ *     backing device supports secure discard.
+ */
+
+/*
+ * STATE DIAGRAMS
+ *
+ *****************************************************************************
+ *                                   Startup                                 *
+ *****************************************************************************
+ *
+ * Tool stack creates front and back nodes with state XenbusStateInitialising.
+ *
+ * Front                                Back
+ * =================================    =====================================
+ * XenbusStateInitialising              XenbusStateInitialising
+ *  o Query virtual device               o Query backend device identification
+ *    properties.                          data.
+ *  o Setup OS device instance.          o Open and validate backend device.
+ *                                       o Publish backend features and
+ *                                         transport parameters.
+ *                                                      |
+ *                                                      |
+ *                                                      V
+ *                                      XenbusStateInitWait
+ *
+ * o Query backend features and
+ *   transport parameters.
+ * o Allocate and initialize the
+ *   request ring.
+ * o Publish transport parameters
+ *   that will be in effect during
+ *   this connection.
+ *              |
+ *              |
+ *              V
+ * XenbusStateInitialised
+ *
+ *                                       o Query frontend transport parameters.
+ *                                       o Connect to the request ring and
+ *                                         event channel.
+ *                                       o Publish backend device properties.
+ *                                                      |
+ *                                                      |
+ *                                                      V
+ *                                      XenbusStateConnected
+ *
+ *  o Query backend device properties.
+ *  o Finalize OS virtual device
+ *    instance.
+ *              |
+ *              |
+ *              V
+ * XenbusStateConnected
+ *
+ * Note: Drivers that do not support any optional features, or the negotiation
+ *       of transport parameters, can skip certain states in the state machine:
+ *
+ *       o A frontend may transition to XenbusStateInitialised without
+ *         waiting for the backend to enter XenbusStateInitWait.  In this
+ *         case, default transport parameters are in effect and any
+ *         transport parameters published by the frontend must contain
+ *         their default values.
+ *
+ *       o A backend may transition to XenbusStateInitialised, bypassing
+ *         XenbusStateInitWait, without waiting for the frontend to first
+ *         enter the XenbusStateInitialised state.  In this case, default
+ *         transport parameters are in effect and any transport parameters
+ *         published by the backend must contain their default values.
+ *
+ *       Drivers that support optional features and/or transport parameter
+ *       negotiation must tolerate these additional state transition paths.
+ *       In general this means performing the work of any skipped state
+ *       transition, if it has not already been performed, in addition to the
+ *       work associated with entry into the current state.
+ */
+
+/*
+ * REQUEST CODES.
+ */
+#define BLKIF_OP_READ              0
+#define BLKIF_OP_WRITE             1
+/*
+ * All writes issued prior to a request with the BLKIF_OP_WRITE_BARRIER
+ * operation code ("barrier request") must be completed prior to the
+ * execution of the barrier request.  All writes issued after the barrier
+ * request must not execute until after the completion of the barrier request.
+ *
+ * Optional.  See "feature-barrier" XenBus node documentation above.
+ */
+#define BLKIF_OP_WRITE_BARRIER     2
+/*
+ * Commit any uncommitted contents of the backing device's volatile cache
+ * to stable storage.
+ *
+ * Optional.  See "feature-flush-cache" XenBus node documentation above.
+ */
+#define BLKIF_OP_FLUSH_DISKCACHE   3
+/*
+ * Used in SLES sources for device specific command packet
+ * contained within the request. Reserved for that purpose.
+ */
+#define BLKIF_OP_RESERVED_1        4
+/*
+ * Indicate to the backend device that a region of storage is no longer in
+ * use, and may be discarded at any time without impact to the client.  If
+ * the BLKIF_DISCARD_SECURE flag is set on the request, all copies of the
+ * discarded region on the device must be rendered unrecoverable before the
+ * command returns.
+ *
+ * This operation is analogous to performing a trim (ATA) or unamp (SCSI),
+ * command on a native device.
+ *
+ * More information about trim/unmap operations can be found at:
+ * http://t13.org/Documents/UploadedDocuments/docs2008/
+ *     e07154r6-Data_Set_Management_Proposal_for_ATA-ACS2.doc
+ * http://www.seagate.com/staticfiles/support/disc/manuals/
+ *     Interface%20manuals/100293068c.pdf
+ *
+ * Optional.  See "feature-discard", "discard-alignment",
+ * "discard-granularity", and "discard-secure" in the XenBus node
+ * documentation above.
+ */
+#define BLKIF_OP_DISCARD           5
+
+/*
+ * Recognized if "feature-max-indirect-segments" in present in the backend
+ * xenbus info. The "feature-max-indirect-segments" node contains the maximum
+ * number of segments allowed by the backend per request. If the node is
+ * present, the frontend might use blkif_request_indirect structs in order to
+ * issue requests with more than BLKIF_MAX_SEGMENTS_PER_REQUEST (11). The
+ * maximum number of indirect segments is fixed by the backend, but the
+ * frontend can issue requests with any number of indirect segments as long as
+ * it's less than the number provided by the backend. The indirect_grefs field
+ * in blkif_request_indirect should be filled by the frontend with the
+ * grant references of the pages that are holding the indirect segments.
+ * These pages are filled with an array of blkif_request_segment that hold the
+ * information about the segments. The number of indirect pages to use is
+ * determined by the number of segments an indirect request contains. Every
+ * indirect page can contain a maximum of
+ * (PAGE_SIZE / sizeof(struct blkif_request_segment)) segments, so to
+ * calculate the number of indirect pages to use we have to do
+ * ceil(indirect_segments / (PAGE_SIZE / sizeof(struct blkif_request_segment))).
+ *
+ * If a backend does not recognize BLKIF_OP_INDIRECT, it should *not*
+ * create the "feature-max-indirect-segments" node!
+ */
+#define BLKIF_OP_INDIRECT          6
+
+/*
+ * Maximum scatter/gather segments per request.
+ * This is carefully chosen so that sizeof(blkif_ring_t) <= PAGE_SIZE.
+ * NB. This could be 12 if the ring indexes weren't stored in the same page.
+ */
+#define BLKIF_MAX_SEGMENTS_PER_REQUEST 11
+
+/*
+ * Maximum number of indirect pages to use per request.
+ */
+#define BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST 8
+
+/*
+ * NB. first_sect and last_sect in blkif_request_segment, as well as
+ * sector_number in blkif_request, are always expressed in 512-byte units.
+ * However they must be properly aligned to the real sector size of the
+ * physical disk, which is reported in the "physical-sector-size" node in
+ * the backend xenbus info. Also the xenbus "sectors" node is expressed in
+ * 512-byte units.
+ */
+struct blkif_request_segment {
+    grant_ref_t gref;        /* reference to I/O buffer frame        */
+    /* @first_sect: first sector in frame to transfer (inclusive).   */
+    /* @last_sect: last sector in frame to transfer (inclusive).     */
+    UINT8     first_sect, last_sect;
+};
+
+/*
+ * Starting ring element for any I/O request.
+ */
+#if defined(__i386__)
+//
+// pack(4) is necessary when these structs are compiled for Ia32.
+// Without it, the struct will have a different alignment than the one
+// a backend expect for a 32bit guest.
+//
+#pragma pack(4)
+#endif
+struct blkif_request {
+    UINT8        operation;    /* BLKIF_OP_???                         */
+    UINT8        nr_segments;  /* number of segments                   */
+    blkif_vdev_t   handle;       /* only for read/write requests         */
+    UINT64       id;           /* private guest value, echoed in resp  */
+    blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+    struct blkif_request_segment seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+};
+typedef struct blkif_request blkif_request_t;
+
+/*
+ * Cast to this structure when blkif_request.operation == BLKIF_OP_DISCARD
+ * sizeof(struct blkif_request_discard) <= sizeof(struct blkif_request)
+ */
+struct blkif_request_discard {
+    UINT8        operation;    /* BLKIF_OP_DISCARD                     */
+    UINT8        flag;         /* BLKIF_DISCARD_SECURE or zero         */
+#define BLKIF_DISCARD_SECURE (1<<0)  /* ignored if discard-secure=0      */
+    blkif_vdev_t   handle;       /* same as for read/write requests      */
+    UINT64       id;           /* private guest value, echoed in resp  */
+    blkif_sector_t sector_number;/* start sector idx on disk             */
+    UINT64       nr_sectors;   /* number of contiguous sectors to discard*/
+};
+typedef struct blkif_request_discard blkif_request_discard_t;
+
+struct blkif_request_indirect {
+    UINT8        operation;    /* BLKIF_OP_INDIRECT                    */
+    UINT8        indirect_op;  /* BLKIF_OP_{READ/WRITE}                */
+    UINT16       nr_segments;  /* number of segments                   */
+    UINT64       id;           /* private guest value, echoed in resp  */
+    blkif_sector_t sector_number;/* start sector idx on disk (r/w only)  */
+    blkif_vdev_t   handle;       /* same as for read/write requests      */
+    grant_ref_t    indirect_grefs[BLKIF_MAX_INDIRECT_PAGES_PER_REQUEST];
+#ifdef __i386__
+    UINT64       pad;          /* Make it 64 byte aligned on i386      */
+#endif
+};
+typedef struct blkif_request_indirect blkif_request_indirect_t;
+
+struct blkif_response {
+    UINT64        id;              /* copied from request */
+    UINT8         operation;       /* copied from request */
+    INT16         status;          /* BLKIF_RSP_???       */
+};
+typedef struct blkif_response blkif_response_t;
+#if defined(__i386__)
+#pragma pack()
+#endif
+
+/*
+ * STATUS RETURN CODES.
+ */
+ /* Operation not supported (only happens on barrier writes). */
+#define BLKIF_RSP_EOPNOTSUPP  -2
+ /* Operation failed for some unspecified reason (-EIO). */
+#define BLKIF_RSP_ERROR       -1
+ /* Operation completed successfully. */
+#define BLKIF_RSP_OKAY         0
+
+/*
+ * Generate blkif ring structures and types.
+ */
+DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response);
+
+#define VDISK_CDROM        0x1
+#define VDISK_REMOVABLE    0x2
+#define VDISK_READONLY     0x4
+
+#endif /* __XEN_PUBLIC_IO_BLKIF_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/OvmfPkg/XenPvBlkDxe/BlockFront.c b/OvmfPkg/XenPvBlkDxe/BlockFront.c
new file mode 100644
index 0000000..a3e1555
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/BlockFront.c
@@ -0,0 +1,647 @@
+/** @file
+  Minimal block driver for Mini-OS.
+
+  Copyright (c) 2007-2008 Samuel Thibault.
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+  SUCH DAMAGE.
+**/
+
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+
+#include "BlockFront.h"
+
+#include <IndustryStandard/Xen/io/protocols.h>
+#include <IndustryStandard/Xen/io/xenbus.h>
+
+//
+// Header used for UINT32_MAX and UINT16_MAX
+//
+#include "inttypes.h"
+
+/**
+  Helper to read an integer from XenStore.
+
+  If the number overflows according to the range defined by UINT64,
+  then ASSERT().
+
+  @param This         A pointer to a XENBUS_PROTOCOL instance.
+  @param Node         The XenStore node to read from.
+  @param FromBackend  Read frontend or backend value.
+  @param ValuePtr     Where to put the value.
+
+  @retval XENSTORE_STATUS_SUCCESS  If succefull, will update ValuePtr.
+  @return                          Any other return value indicate the error,
+                                   ValuePtr is not updated in this case.
+**/
+STATIC
+XENSTORE_STATUS
+XenBusReadUint64 (
+  IN  XENBUS_PROTOCOL *This,
+  IN  CONST CHAR8     *Node,
+  IN  BOOLEAN         FromBackend,
+  OUT UINT64          *ValuePtr
+  )
+{
+  XENSTORE_STATUS Status;
+  CHAR8 *Ptr;
+
+  if (!FromBackend) {
+    Status = This->XsRead (This, XST_NIL, Node, (VOID**)&Ptr);
+  } else {
+    Status = This->XsBackendRead (This, XST_NIL, Node, (VOID**)&Ptr);
+  }
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    return Status;
+  }
+  // AsciiStrDecimalToUint64 will ASSERT if Ptr overflow UINT64.
+  *ValuePtr = AsciiStrDecimalToUint64 (Ptr);
+  FreePool (Ptr);
+  return Status;
+}
+
+/**
+  Free an instance of XEN_BLOCK_FRONT_DEVICE.
+
+  @param Dev  The instance to free.
+**/
+STATIC
+VOID
+XenPvBlockFree (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  )
+{
+  XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
+
+  if (Dev->RingRef != 0) {
+    XenBusIo->GrantEndAccess (XenBusIo, Dev->RingRef);
+  }
+  if (Dev->Ring.sring != NULL) {
+    FreePages (Dev->Ring.sring, 1);
+  }
+  if (Dev->EventChannel != 0) {
+    XenBusIo->EventChannelClose (XenBusIo, Dev->EventChannel);
+  }
+  FreePool (Dev);
+}
+
+/**
+  Wait until until the backend has reached the ExpectedState.
+
+  @param Dev            A XEN_BLOCK_FRONT_DEVICE instance.
+  @param ExpectedState  The backend state expected.
+  @param LastStatePtr   An optional pointer where to right the final state.
+
+  @return Return XENSTORE_STATUS_SUCCESS if the new backend state is ExpectedState
+          or return an error otherwise.
+**/
+STATIC
+XENSTORE_STATUS
+XenPvBlkWaitForBackendState (
+  IN  XEN_BLOCK_FRONT_DEVICE *Dev,
+  IN  XenbusState            ExpectedState,
+  OUT XenbusState            *LastStatePtr OPTIONAL
+  )
+{
+  XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
+  XenbusState State;
+  UINT64 Value;
+  XENSTORE_STATUS Status = XENSTORE_STATUS_SUCCESS;
+
+  while (TRUE) {
+    Status = XenBusReadUint64 (XenBusIo, "state", TRUE, &Value);
+    if (Status != XENSTORE_STATUS_SUCCESS) {
+      return Status;
+    }
+    if (Value > XenbusStateReconfigured) {
+      //
+      // Value is not a State value.
+      //
+      return XENSTORE_STATUS_EIO;
+    }
+    State = Value;
+    if (State == ExpectedState) {
+      break;
+    } else if (State > ExpectedState) {
+      Status = XENSTORE_STATUS_FAIL;
+      break;
+    }
+    DEBUG ((EFI_D_INFO,
+            "XenPvBlk: waiting backend state %d, current: %d\n",
+            ExpectedState, State));
+    XenBusIo->WaitForWatch (XenBusIo, Dev->StateWatchToken);
+  }
+
+  if (LastStatePtr != NULL) {
+    *LastStatePtr = State;
+  }
+
+  return Status;
+}
+
+EFI_STATUS
+XenPvBlockFrontInitialization (
+  IN  XENBUS_PROTOCOL         *XenBusIo,
+  IN  CONST CHAR8             *NodeName,
+  OUT XEN_BLOCK_FRONT_DEVICE  **DevPtr
+  )
+{
+  XENSTORE_TRANSACTION xbt;
+  CHAR8 *DeviceType;
+  blkif_sring_t *SharedRing;
+  XENSTORE_STATUS Status;
+  XEN_BLOCK_FRONT_DEVICE *Dev;
+  XenbusState State;
+  UINT64 Value;
+
+  ASSERT (NodeName != NULL);
+
+  Dev = AllocateZeroPool (sizeof (XEN_BLOCK_FRONT_DEVICE));
+  Dev->Signature = XEN_BLOCK_FRONT_SIGNATURE;
+  Dev->NodeName = NodeName;
+  Dev->XenBusIo = XenBusIo;
+  Dev->DeviceId = XenBusIo->DeviceId;
+
+  XenBusIo->XsRead (XenBusIo, XST_NIL, "device-type", (VOID**)&DeviceType);
+  if (AsciiStrCmp (DeviceType, "cdrom") == 0) {
+    Dev->MediaInfo.CdRom = TRUE;
+  } else {
+    Dev->MediaInfo.CdRom = FALSE;
+  }
+  FreePool (DeviceType);
+
+  Status = XenBusReadUint64 (XenBusIo, "backend-id", FALSE, &Value);
+  if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT16_MAX) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to get backend-id (%d)\n",
+            Status));
+    goto Error;
+  }
+  Dev->DomainId = Value;
+  XenBusIo->EventChannelAllocate (XenBusIo, Dev->DomainId, &Dev->EventChannel);
+
+  SharedRing = (blkif_sring_t*) AllocatePages (1);
+  SHARED_RING_INIT (SharedRing);
+  FRONT_RING_INIT (&Dev->Ring, SharedRing, EFI_PAGE_SIZE);
+  XenBusIo->GrantAccess (XenBusIo,
+                         Dev->DomainId,
+                         (INTN) SharedRing >> EFI_PAGE_SHIFT,
+                         FALSE,
+                         &Dev->RingRef);
+
+Again:
+  Status = XenBusIo->XsTransactionStart (XenBusIo, &xbt);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_WARN, "XenPvBlk: Failed to start transaction, %d\n", Status));
+    goto Error;
+  }
+
+  Status = XenBusIo->XsPrintf (XenBusIo, xbt, NodeName, "ring-ref", "%d",
+                               Dev->RingRef);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write ring-ref.\n"));
+    goto AbortTransaction;
+  }
+  Status = XenBusIo->XsPrintf (XenBusIo, xbt, NodeName,
+                               "event-channel", "%d", Dev->EventChannel);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write event-channel.\n"));
+    goto AbortTransaction;
+  }
+  Status = XenBusIo->XsPrintf (XenBusIo, xbt, NodeName,
+                               "protocol", "%a", XEN_IO_PROTO_ABI_NATIVE);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write protocol.\n"));
+    goto AbortTransaction;
+  }
+
+  Status = XenBusIo->SetState (XenBusIo, xbt, XenbusStateConnected);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to switch state.\n"));
+    goto AbortTransaction;
+  }
+
+  Status = XenBusIo->XsTransactionEnd (XenBusIo, xbt, FALSE);
+  if (Status == XENSTORE_STATUS_EAGAIN) {
+    goto Again;
+  }
+
+  XenBusIo->RegisterWatchBackend (XenBusIo, "state", &Dev->StateWatchToken);
+
+  //
+  // Waiting for backend
+  //
+  Status = XenPvBlkWaitForBackendState (Dev, XenbusStateConnected, &State);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR,
+            "XenPvBlk: backend for %a/%d not available, rc=%d state=%d\n",
+            XenBusIo->Type, XenBusIo->DeviceId, Status, State));
+    goto Error2;
+  }
+
+  Status = XenBusReadUint64 (XenBusIo, "info", TRUE, &Value);
+  if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT32_MAX) {
+    goto Error2;
+  }
+  Dev->MediaInfo.VDiskInfo = Value;
+  if (Dev->MediaInfo.VDiskInfo & VDISK_READONLY) {
+    Dev->MediaInfo.ReadWrite = FALSE;
+  } else {
+    Dev->MediaInfo.ReadWrite = TRUE;
+  }
+
+  Status = XenBusReadUint64 (XenBusIo, "sectors", TRUE, &Dev->MediaInfo.Sectors);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    goto Error2;
+  }
+
+  Status = XenBusReadUint64 (XenBusIo, "sector-size", TRUE, &Value);
+  if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT32_MAX) {
+    goto Error2;
+  }
+  if (Value % 512 != 0) {
+    //
+    // This is not supported by the driver.
+    //
+    DEBUG ((EFI_D_ERROR, "XenPvBlk: Unsupported sector-size value %d, "
+            "it must be a multiple of 512\n", Value));
+    goto Error2;
+  }
+  Dev->MediaInfo.SectorSize = Value;
+
+  // Default value
+  Value = 0;
+  XenBusReadUint64 (XenBusIo, "feature-barrier", TRUE, &Value);
+  if (Value == 1) {
+    Dev->MediaInfo.FeatureBarrier = TRUE;
+  } else {
+    Dev->MediaInfo.FeatureBarrier = FALSE;
+  }
+
+  // Default value
+  Value = 0;
+  XenBusReadUint64 (XenBusIo, "feature-flush-cache", TRUE, &Value);
+  if (Value == 1) {
+    Dev->MediaInfo.FeatureFlushCache = TRUE;
+  } else {
+    Dev->MediaInfo.FeatureFlushCache = FALSE;
+  }
+
+  DEBUG ((EFI_D_INFO, "XenPvBlk: New disk with %ld sectors of %d bytes\n",
+          Dev->MediaInfo.Sectors, Dev->MediaInfo.SectorSize));
+
+  *DevPtr = Dev;
+  return EFI_SUCCESS;
+
+Error2:
+  XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
+  XenBusIo->XsRemove (XenBusIo, XST_NIL, "ring-ref");
+  XenBusIo->XsRemove (XenBusIo, XST_NIL, "event-channel");
+  XenBusIo->XsRemove (XenBusIo, XST_NIL, "protocol");
+  goto Error;
+AbortTransaction:
+  XenBusIo->XsTransactionEnd (XenBusIo, xbt, TRUE);
+Error:
+  XenPvBlockFree (Dev);
+  return EFI_DEVICE_ERROR;
+}
+
+VOID
+XenPvBlockFrontShutdown (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  )
+{
+  XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
+  XENSTORE_STATUS Status;
+  UINT64 Value;
+
+  XenPvBlockSync (Dev);
+
+  Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosing);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR,
+            "XenPvBlk: error while changing state to Closing: %d\n",
+            Status));
+    goto Close;
+  }
+
+  Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosing, NULL);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR,
+            "XenPvBlk: error while waiting for closing backend state: %d\n",
+            Status));
+    goto Close;
+  }
+
+  Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateClosed);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR,
+            "XenPvBlk: error while changing state to Closed: %d\n",
+            Status));
+    goto Close;
+  }
+
+  Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosed, NULL);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR,
+            "XenPvBlk: error while waiting for closed backend state: %d\n",
+            Status));
+    goto Close;
+  }
+
+  Status = XenBusIo->SetState (XenBusIo, XST_NIL, XenbusStateInitialising);
+  if (Status != XENSTORE_STATUS_SUCCESS) {
+    DEBUG ((EFI_D_ERROR,
+            "XenPvBlk: error while changing state to initialising: %d\n",
+            Status));
+    goto Close;
+  }
+
+  while (TRUE) {
+    Status = XenBusReadUint64 (XenBusIo, "state", TRUE, &Value);
+    if (Status != XENSTORE_STATUS_SUCCESS) {
+      DEBUG ((EFI_D_ERROR,
+              "XenPvBlk: error while waiting for new backend state: %d\n",
+              Status));
+      goto Close;
+    }
+    if (Value <= XenbusStateInitWait || Value >= XenbusStateClosed) {
+      break;
+    }
+    DEBUG ((EFI_D_INFO,
+            "XenPvBlk: waiting backend state %d, current: %d\n",
+            XenbusStateInitWait, Value));
+    XenBusIo->WaitForWatch (XenBusIo, Dev->StateWatchToken);
+  }
+
+Close:
+  XenBusIo->UnregisterWatch (XenBusIo, Dev->StateWatchToken);
+  XenBusIo->XsRemove (XenBusIo, XST_NIL, "ring-ref");
+  XenBusIo->XsRemove (XenBusIo, XST_NIL, "event-channel");
+  XenBusIo->XsRemove (XenBusIo, XST_NIL, "protocol");
+
+  XenPvBlockFree (Dev);
+}
+
+STATIC
+VOID
+XenPvBlockWaitSlot (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  )
+{
+  /* Wait for a slot */
+  if (RING_FULL (&Dev->Ring)) {
+    while (TRUE) {
+      XenPvBlockAsyncIoPoll (Dev);
+      if (!RING_FULL (&Dev->Ring)) {
+        break;
+      }
+      /* Really no slot, could wait for an event on Dev->EventChannel. */
+    }
+  }
+}
+
+VOID
+XenPvBlockAsyncIo (
+  IN OUT XEN_BLOCK_FRONT_IO *IoData,
+  IN     BOOLEAN            IsWrite
+  )
+{
+  XEN_BLOCK_FRONT_DEVICE *Dev = IoData->Dev;
+  XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
+  blkif_request_t *Request;
+  RING_IDX RingIndex;
+  BOOLEAN Notify;
+  INT32 NumSegments, Index;
+  UINTN Start, End;
+
+  // Can't io at non-sector-aligned location
+  ASSERT(!(IoData->Sector & ((Dev->MediaInfo.SectorSize / 512) - 1)));
+  // Can't io non-sector-sized amounts
+  ASSERT(!(IoData->Size & (Dev->MediaInfo.SectorSize - 1)));
+  // Can't io non-sector-aligned buffer
+  ASSERT(!((UINTN) IoData->Buffer & (Dev->MediaInfo.SectorSize - 1)));
+
+  Start = (UINTN) IoData->Buffer & ~EFI_PAGE_MASK;
+  End = ((UINTN) IoData->Buffer + IoData->Size + EFI_PAGE_SIZE - 1) & ~EFI_PAGE_MASK;
+  IoData->NumRef = NumSegments = (End - Start) / EFI_PAGE_SIZE;
+
+  ASSERT (NumSegments <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
+
+  XenPvBlockWaitSlot (Dev);
+  RingIndex = Dev->Ring.req_prod_pvt;
+  Request = RING_GET_REQUEST (&Dev->Ring, RingIndex);
+
+  Request->operation = IsWrite ? BLKIF_OP_WRITE : BLKIF_OP_READ;
+  Request->nr_segments = NumSegments;
+  Request->handle = Dev->DeviceId;
+  Request->id = (UINTN) IoData;
+  Request->sector_number = IoData->Sector;
+
+  for (Index = 0; Index < NumSegments; Index++) {
+    Request->seg[Index].first_sect = 0;
+    Request->seg[Index].last_sect = EFI_PAGE_SIZE / 512 - 1;
+  }
+  Request->seg[0].first_sect = ((UINTN) IoData->Buffer & EFI_PAGE_MASK) / 512;
+  Request->seg[NumSegments - 1].last_sect =
+      (((UINTN) IoData->Buffer + IoData->Size - 1) & EFI_PAGE_MASK) / 512;
+  for (Index = 0; Index < NumSegments; Index++) {
+    UINTN Data = Start + Index * EFI_PAGE_SIZE;
+    XenBusIo->GrantAccess (XenBusIo, Dev->DomainId,
+                           Data >> EFI_PAGE_SHIFT, IsWrite,
+                           &Request->seg[Index].gref);
+    IoData->GrantRef[Index] = Request->seg[Index].gref;
+  }
+
+  Dev->Ring.req_prod_pvt = RingIndex + 1;
+
+  MemoryFence ();
+  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
+
+  if (Notify) {
+    UINT32 ReturnCode;
+    ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
+    if (ReturnCode != 0) {
+      DEBUG ((EFI_D_ERROR,
+              "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
+              ReturnCode));
+    }
+  }
+}
+
+EFI_STATUS
+XenPvBlockIo (
+  IN OUT XEN_BLOCK_FRONT_IO *IoData,
+  IN     BOOLEAN            IsWrite
+  )
+{
+  //
+  // Status value that correspond to an IO in progress.
+  //
+  IoData->Status = EFI_ALREADY_STARTED;
+  XenPvBlockAsyncIo (IoData, IsWrite);
+
+  while (IoData->Status == EFI_ALREADY_STARTED) {
+    XenPvBlockAsyncIoPoll (IoData->Dev);
+  }
+
+  return IoData->Status;
+}
+
+STATIC
+VOID
+XenPvBlockPushOperation (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev,
+  IN UINT8                  Operation,
+  IN UINT64                 Id
+  )
+{
+  INT32 Index;
+  blkif_request_t *Request;
+  BOOLEAN Notify;
+
+  XenPvBlockWaitSlot (Dev);
+  Index = Dev->Ring.req_prod_pvt;
+  Request = RING_GET_REQUEST(&Dev->Ring, Index);
+  Request->operation = Operation;
+  Request->nr_segments = 0;
+  Request->handle = Dev->DeviceId;
+  Request->id = Id;
+  /* Not needed anyway, but the backend will check it */
+  Request->sector_number = 0;
+  Dev->Ring.req_prod_pvt = Index + 1;
+  MemoryFence ();
+  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify);
+  if (Notify) {
+    XENBUS_PROTOCOL *XenBusIo = Dev->XenBusIo;
+    UINT32 ReturnCode;
+    ReturnCode = XenBusIo->EventChannelNotify (XenBusIo, Dev->EventChannel);
+    if (ReturnCode != 0) {
+      DEBUG ((EFI_D_ERROR,
+              "XenPvBlk: Unexpected return value from EventChannelNotify: %d\n",
+              ReturnCode));
+    }
+  }
+}
+
+VOID
+XenPvBlockSync (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  )
+{
+  if (Dev->MediaInfo.ReadWrite) {
+    if (Dev->MediaInfo.FeatureBarrier) {
+      XenPvBlockPushOperation (Dev, BLKIF_OP_WRITE_BARRIER, 0);
+    }
+
+    if (Dev->MediaInfo.FeatureFlushCache) {
+      XenPvBlockPushOperation (Dev, BLKIF_OP_FLUSH_DISKCACHE, 0);
+    }
+  }
+
+  /* Note: This won't finish if another thread enqueues requests.  */
+  while (TRUE) {
+    XenPvBlockAsyncIoPoll (Dev);
+    if (RING_FREE_REQUESTS (&Dev->Ring) == RING_SIZE (&Dev->Ring)) {
+      break;
+    }
+  }
+}
+
+VOID
+XenPvBlockAsyncIoPoll (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  )
+{
+  RING_IDX ProducerIndex, ConsumerIndex;
+  blkif_response_t *Response;
+  INT32 More;
+
+  do {
+    ProducerIndex = Dev->Ring.sring->rsp_prod;
+    /* Ensure we see queued responses up to 'ProducerIndex'. */
+    MemoryFence ();
+    ConsumerIndex = Dev->Ring.rsp_cons;
+
+    while (ConsumerIndex != ProducerIndex) {
+      XEN_BLOCK_FRONT_IO *IoData = NULL;
+      INT16 Status;
+
+      Response = RING_GET_RESPONSE (&Dev->Ring, ConsumerIndex);
+
+      IoData = (VOID *) (UINTN) Response->id;
+      Status = Response->status;
+
+      switch (Response->operation) {
+      case BLKIF_OP_READ:
+      case BLKIF_OP_WRITE:
+        {
+          INT32 Index;
+
+          if (Status != BLKIF_RSP_OKAY) {
+            DEBUG ((EFI_D_ERROR,
+                    "XenPvBlk: "
+                    "%a error %d on %a at sector %p, num bytes %p\n",
+                    Response->operation == BLKIF_OP_READ ? "read" : "write",
+                    Status, IoData->Dev->NodeName,
+                    IoData->Sector,
+                    IoData->Size));
+          }
+
+          for (Index = 0; Index < IoData->NumRef; Index++) {
+            Dev->XenBusIo->GrantEndAccess (Dev->XenBusIo, IoData->GrantRef[Index]);
+          }
+
+          break;
+        }
+
+      case BLKIF_OP_WRITE_BARRIER:
+        if (Status != BLKIF_RSP_OKAY) {
+          DEBUG ((EFI_D_ERROR, "XenPvBlk: write barrier error %d\n", Status));
+        }
+        break;
+      case BLKIF_OP_FLUSH_DISKCACHE:
+        if (Status != BLKIF_RSP_OKAY) {
+          DEBUG ((EFI_D_ERROR, "XenPvBlk: flush error %d\n", Status));
+        }
+        break;
+
+      default:
+        DEBUG ((EFI_D_ERROR,
+                "XenPvBlk: unrecognized block operation %d response (status %d)\n",
+                Response->operation, Status));
+        break;
+      }
+
+      Dev->Ring.rsp_cons = ++ConsumerIndex;
+      if (IoData != NULL) {
+        IoData->Status = Status ? EFI_DEVICE_ERROR : EFI_SUCCESS;
+      }
+      if (Dev->Ring.rsp_cons != ConsumerIndex) {
+        /* We reentered, we must not continue here */
+        break;
+      }
+    }
+
+    RING_FINAL_CHECK_FOR_RESPONSES (&Dev->Ring, More);
+  } while (More != 0);
+}
diff --git a/OvmfPkg/XenPvBlkDxe/BlockFront.h b/OvmfPkg/XenPvBlkDxe/BlockFront.h
new file mode 100644
index 0000000..761f09b
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/BlockFront.h
@@ -0,0 +1,87 @@
+#include "XenPvBlkDxe.h"
+
+#include <IndustryStandard/Xen/event_channel.h>
+#include <IndustryStandard/Xen/io/blkif.h>
+
+typedef struct _XEN_BLOCK_FRONT_DEVICE XEN_BLOCK_FRONT_DEVICE;
+typedef struct _XEN_BLOCK_FRONT_IO XEN_BLOCK_FRONT_IO;
+
+struct _XEN_BLOCK_FRONT_IO
+{
+  XEN_BLOCK_FRONT_DEVICE  *Dev;
+  UINT8                   *Buffer;
+  UINTN                   Size;
+  UINTN                   Sector; ///< 512 bytes sector.
+
+  grant_ref_t             GrantRef[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+  INT32                   NumRef;
+
+  EFI_STATUS              Status;
+};
+
+typedef struct
+{
+  UINT64    Sectors;
+  UINT32    SectorSize;
+  UINT32    VDiskInfo;
+  BOOLEAN   ReadWrite;
+  BOOLEAN   CdRom;
+  BOOLEAN   FeatureBarrier;
+  BOOLEAN   FeatureFlushCache;
+} XEN_BLOCK_FRONT_MEDIA_INFO;
+
+#define XEN_BLOCK_FRONT_SIGNATURE SIGNATURE_32 ('X', 'p', 'v', 'B')
+struct _XEN_BLOCK_FRONT_DEVICE {
+  UINT32                      Signature;
+  EFI_BLOCK_IO_PROTOCOL       BlockIo;
+  domid_t                     DomainId;
+
+  blkif_front_ring_t          Ring;
+  grant_ref_t                 RingRef;
+  evtchn_port_t               EventChannel;
+  blkif_vdev_t                DeviceId;
+
+  CONST CHAR8                 *NodeName;
+  XEN_BLOCK_FRONT_MEDIA_INFO  MediaInfo;
+
+  VOID                        *StateWatchToken;
+
+  XENBUS_PROTOCOL             *XenBusIo;
+};
+
+#define XEN_BLOCK_FRONT_FROM_BLOCK_IO(b) \
+  CR (b, XEN_BLOCK_FRONT_DEVICE, BlockIo, XEN_BLOCK_FRONT_SIGNATURE)
+
+EFI_STATUS
+XenPvBlockFrontInitialization (
+  IN  XENBUS_PROTOCOL  *XenBusIo,
+  IN  CONST CHAR8      *NodeName,
+  OUT XEN_BLOCK_FRONT_DEVICE **DevPtr
+  );
+
+VOID
+XenPvBlockFrontShutdown (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  );
+
+VOID
+XenPvBlockAsyncIo (
+  IN OUT XEN_BLOCK_FRONT_IO *IoData,
+  IN     BOOLEAN            IsWrite
+  );
+
+EFI_STATUS
+XenPvBlockIo (
+  IN OUT XEN_BLOCK_FRONT_IO *IoData,
+  IN     BOOLEAN            IsWrite
+  );
+
+VOID
+XenPvBlockAsyncIoPoll (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  );
+
+VOID
+XenPvBlockSync (
+  IN XEN_BLOCK_FRONT_DEVICE *Dev
+  );
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
index ad45e69..a732a04 100644
--- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
@@ -36,6 +36,8 @@
 
 #include "XenPvBlkDxe.h"
 
+#include "BlockFront.h"
+
 
 ///
 /// Driver Binding Protocol instance
@@ -274,6 +276,7 @@ XenPvBlkDxeDriverBindingStart (
 {
   EFI_STATUS Status;
   XENBUS_PROTOCOL *XenBusIo;
+  XEN_BLOCK_FRONT_DEVICE *Dev;
 
   Status = gBS->OpenProtocol (
                 ControllerHandle,
@@ -287,7 +290,17 @@ XenPvBlkDxeDriverBindingStart (
     return Status;
   }
 
+  Status = XenPvBlockFrontInitialization (XenBusIo, XenBusIo->Node, &Dev);
+  if (EFI_ERROR (Status)) {
+    goto CloseProtocol;
+  }
+
   return EFI_SUCCESS;
+
+CloseProtocol:
+  gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
+                      This->DriverBindingHandle, ControllerHandle);
+  return Status;
 }
 
 /**
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
index 4103996..9a6e17b 100644
--- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
@@ -50,6 +50,8 @@
   XenPvBlkDxe.c
   ComponentName.c
   ComponentName.h
+  BlockFront.c
+  BlockFront.h
 
 
 [LibraryClasses]
-- 
Anthony PERARD

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

* [PATCH v3 19/19] OvmfPkg/XenPvBlkDxe: Add BlockIo.
       [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
                   ` (17 preceding siblings ...)
  2014-10-17 17:04 ` [PATCH v3 18/19] OvmfPkg/XenPvBlkDxe: Add BlockFront client Anthony PERARD
@ 2014-10-17 17:04 ` Anthony PERARD
       [not found] ` <1413565442-29149-4-git-send-email-anthony.perard@citrix.com>
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-17 17:04 UTC (permalink / raw)
  To: EDK2 devel; +Cc: Anthony PERARD, Xen Devel

Implement the BlockIo protocol.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>

---
Change in V3:
- assert(Media->BlockSize % 512 == 0)
- Use Sector instead of Offset to issue IOs.

Change in V2:
- Remove blockIo2 headers.
- Fix few comment.
- file header, copyright
- Rewrite few comment and error messages
- No more callback
- Improving block read/write, increase to the max size in one request
  (instead of only 8pages)
- Fix lastblock when it's a cdrom
- Do uninitialisation when fail to install fail
- few comment
- Licenses
---
 OvmfPkg/XenPvBlkDxe/BlockIo.c       | 290 ++++++++++++++++++++++++++++++++++++
 OvmfPkg/XenPvBlkDxe/BlockIo.h       | 124 +++++++++++++++
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c   |  65 ++++++++
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h   |   1 +
 OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf |   2 +
 5 files changed, 482 insertions(+)
 create mode 100644 OvmfPkg/XenPvBlkDxe/BlockIo.c
 create mode 100644 OvmfPkg/XenPvBlkDxe/BlockIo.h

diff --git a/OvmfPkg/XenPvBlkDxe/BlockIo.c b/OvmfPkg/XenPvBlkDxe/BlockIo.c
new file mode 100644
index 0000000..17b7b8f
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/BlockIo.c
@@ -0,0 +1,290 @@
+/** @file
+  BlockIo implementation for Xen PV Block driver.
+
+  This file is implementing the interface between the actual driver in
+  BlockFront.c to the BlockIo protocol.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+#include "XenPvBlkDxe.h"
+
+#include "BlockFront.h"
+
+///
+/// Block I/O Media structure
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_BLOCK_IO_MEDIA  gXenPvBlkDxeBlockIoMedia = {
+  0,      // MediaId
+  FALSE,  // RemovableMedia
+  FALSE,  // MediaPresent
+  FALSE,  // LogicalPartition
+  TRUE,   // ReadOnly
+  FALSE,  // WriteCaching
+  512,    // BlockSize
+  512,    // IoAlign, BlockFront does not support less than 512 bits-aligned.
+  0,      // LastBlock
+  0,      // LowestAlignedLba
+  0,      // LogicalBlocksPerPhysicalBlock
+  0       // OptimalTransferLengthGranularity
+};
+
+///
+/// Block I/O Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_BLOCK_IO_PROTOCOL  gXenPvBlkDxeBlockIo = {
+  EFI_BLOCK_IO_PROTOCOL_REVISION3,          // Revision
+  &gXenPvBlkDxeBlockIoMedia,                // Media
+  XenPvBlkDxeBlockIoReset,                  // Reset
+  XenPvBlkDxeBlockIoReadBlocks,             // ReadBlocks
+  XenPvBlkDxeBlockIoWriteBlocks,            // WriteBlocks
+  XenPvBlkDxeBlockIoFlushBlocks             // FlushBlocks
+};
+
+
+
+
+/**
+  Read/Write BufferSize bytes from Lba into Buffer.
+
+  This function is commun to XenPvBlkDxeBlockIoReadBlocks and
+  XenPvBlkDxeBlockIoWriteBlocks.
+
+  @param  This       Indicates a pointer to the calling context.
+  @param  MediaId    Id of the media, changes every time the media is replaced.
+  @param  Lba        The starting Logical Block Address to read from/write to.
+  @param  BufferSize Size of Buffer, must be a multiple of device block size.
+  @param  Buffer     A pointer to the destination/source buffer for the data.
+  @param  IsWrite    Indicate if the operation is write or read.
+
+  @return See description of XenPvBlkDxeBlockIoReadBlocks and
+          XenPvBlkDxeBlockIoWriteBlocks.
+**/
+STATIC
+EFI_STATUS
+XenPvBlkDxeBlockIoReadWriteBlocks (
+  IN     EFI_BLOCK_IO_PROTOCOL  *This,
+  IN     UINT32                 MediaId,
+  IN     EFI_LBA                Lba,
+  IN     UINTN                  BufferSize,
+  IN OUT VOID                   *Buffer,
+  IN     BOOLEAN                IsWrite
+  )
+{
+  XEN_BLOCK_FRONT_IO IoData;
+  EFI_BLOCK_IO_MEDIA *Media = This->Media;
+  UINTN Sector;
+  EFI_STATUS Status;
+
+  if (Buffer == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  if (BufferSize == 0) {
+    return EFI_SUCCESS;
+  }
+
+  if (BufferSize % Media->BlockSize != 0) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlkDxe: Bad buffer size: 0x%X\n", BufferSize));
+    return EFI_BAD_BUFFER_SIZE;
+  }
+
+  if (Lba > Media->LastBlock ||
+      (BufferSize / Media->BlockSize) - 1 > Media->LastBlock - Lba) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlkDxe: %a with invalid LBA: 0x%LX, size: 0x%x\n",
+            IsWrite ? "Write" : "Read", Lba, BufferSize));
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (IsWrite && Media->ReadOnly) {
+    return EFI_WRITE_PROTECTED;
+  }
+
+  if ((Media->IoAlign > 1) && (UINTN)Buffer & (Media->IoAlign - 1)) {
+    //
+    // Grub2 does not appear to respect IoAlign of 512, so reallocate the
+    // buffer here.
+    //
+    VOID *NewBuffer;
+
+    //
+    // Try again with a properly aligned buffer.
+    //
+    NewBuffer = AllocateAlignedPages((BufferSize + EFI_PAGE_SIZE) / EFI_PAGE_SIZE,
+                                     Media->IoAlign);
+    if (!IsWrite) {
+      Status = XenPvBlkDxeBlockIoReadBlocks (This, MediaId,
+                                             Lba, BufferSize, NewBuffer);
+      CopyMem (Buffer, NewBuffer, BufferSize);
+    } else {
+      CopyMem (NewBuffer, Buffer, BufferSize);
+      Status = XenPvBlkDxeBlockIoWriteBlocks (This, MediaId,
+                                              Lba, BufferSize, NewBuffer);
+    }
+    FreeAlignedPages (NewBuffer, (BufferSize + EFI_PAGE_SIZE) / EFI_PAGE_SIZE);
+    return Status;
+  }
+
+  IoData.Dev = XEN_BLOCK_FRONT_FROM_BLOCK_IO (This);
+  Sector = Lba * (Media->BlockSize / 512);
+
+  while (BufferSize > 0) {
+    if (((UINTN)Buffer & EFI_PAGE_MASK) == 0) {
+      IoData.Size = MIN (BLKIF_MAX_SEGMENTS_PER_REQUEST * EFI_PAGE_SIZE,
+                         BufferSize);
+    } else {
+      IoData.Size = MIN ((BLKIF_MAX_SEGMENTS_PER_REQUEST - 1) * EFI_PAGE_SIZE,
+                         BufferSize);
+    }
+
+    IoData.Buffer = Buffer;
+    IoData.Sector = Sector;
+    BufferSize -= IoData.Size;
+    Buffer = (VOID*) ((UINTN) Buffer + IoData.Size);
+    Sector += IoData.Size / 512;
+    Status = XenPvBlockIo (&IoData, IsWrite);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((EFI_D_ERROR, "XenPvBlkDxe: Error durring %a operation.\n",
+              IsWrite ? "write" : "read"));
+      return Status;
+    }
+  }
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Read BufferSize bytes from Lba into Buffer.
+
+  @param  This       Indicates a pointer to the calling context.
+  @param  MediaId    Id of the media, changes every time the media is replaced.
+  @param  Lba        The starting Logical Block Address to read from
+  @param  BufferSize Size of Buffer, must be a multiple of device block size.
+  @param  Buffer     A pointer to the destination buffer for the data. The caller is
+                     responsible for either having implicit or explicit ownership of the buffer.
+
+  @retval EFI_SUCCESS           The data was read correctly from the device.
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
+  @retval EFI_NO_MEDIA          There is no media in the device.
+  @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
+  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+                                or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoReadBlocks (
+  IN  EFI_BLOCK_IO_PROTOCOL         *This,
+  IN  UINT32                        MediaId,
+  IN  EFI_LBA                       Lba,
+  IN  UINTN                         BufferSize,
+  OUT VOID                          *Buffer
+  )
+{
+  return XenPvBlkDxeBlockIoReadWriteBlocks (This,
+      MediaId, Lba, BufferSize, Buffer, FALSE);
+}
+
+/**
+  Write BufferSize bytes from Lba into Buffer.
+
+  @param  This       Indicates a pointer to the calling context.
+  @param  MediaId    The media ID that the write request is for.
+  @param  Lba        The starting logical block address to be written. The caller is
+                     responsible for writing to only legitimate locations.
+  @param  BufferSize Size of Buffer, must be a multiple of device block size.
+  @param  Buffer     A pointer to the source buffer for the data.
+
+  @retval EFI_SUCCESS           The data was written correctly to the device.
+  @retval EFI_WRITE_PROTECTED   The device can not be written to.
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
+  @retval EFI_NO_MEDIA          There is no media in the device.
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
+  @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+                                or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoWriteBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL          *This,
+  IN UINT32                         MediaId,
+  IN EFI_LBA                        Lba,
+  IN UINTN                          BufferSize,
+  IN VOID                           *Buffer
+  )
+{
+  return XenPvBlkDxeBlockIoReadWriteBlocks (This,
+      MediaId, Lba, BufferSize, Buffer, TRUE);
+}
+
+/**
+  Flush the Block Device.
+
+  @param  This              Indicates a pointer to the calling context.
+
+  @retval EFI_SUCCESS       All outstanding data was written to the device
+  @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
+  @retval EFI_NO_MEDIA      There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoFlushBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This
+  )
+{
+  XenPvBlockSync (XEN_BLOCK_FRONT_FROM_BLOCK_IO (This));
+  return EFI_SUCCESS;
+}
+
+/**
+  Reset the block device hardware.
+
+  @param[in]  This                 Indicates a pointer to the calling context.
+  @param[in]  ExtendedVerification Not used.
+
+  @retval EFI_SUCCESS          The device was reset.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoReset (
+  IN EFI_BLOCK_IO_PROTOCOL   *This,
+  IN BOOLEAN                 ExtendedVerification
+  )
+{
+  //
+  // Since the initialization of the devices is done, then the device is
+  // working correctly.
+  //
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/XenPvBlkDxe/BlockIo.h b/OvmfPkg/XenPvBlkDxe/BlockIo.h
new file mode 100644
index 0000000..22b6de2
--- /dev/null
+++ b/OvmfPkg/XenPvBlkDxe/BlockIo.h
@@ -0,0 +1,124 @@
+/** @file
+  BlockIo function declaration for Xen PV block driver.
+
+  Copyright (C) 2014, Citrix Ltd.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+  POSSIBILITY OF SUCH DAMAGE.
+
+**/
+
+/**
+  Read BufferSize bytes from Lba into Buffer.
+
+  @param  This       Indicates a pointer to the calling context.
+  @param  MediaId    Id of the media, changes every time the media is replaced.
+  @param  Lba        The starting Logical Block Address to read from
+  @param  BufferSize Size of Buffer, must be a multiple of device block size.
+  @param  Buffer     A pointer to the destination buffer for the data. The caller is
+                     responsible for either having implicit or explicit ownership of the buffer.
+
+  @retval EFI_SUCCESS           The data was read correctly from the device.
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the read.
+  @retval EFI_NO_MEDIA          There is no media in the device.
+  @retval EFI_MEDIA_CHANGED     The MediaId does not matched the current device.
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
+  @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
+                                or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoReadBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL          *This,
+  IN UINT32                         MediaId,
+  IN EFI_LBA                        Lba,
+  IN UINTN                          BufferSize,
+  OUT VOID                          *Buffer
+  );
+
+/**
+  Write BufferSize bytes from Lba into Buffer.
+
+  @param  This       Indicates a pointer to the calling context.
+  @param  MediaId    The media ID that the write request is for.
+  @param  Lba        The starting logical block address to be written. The caller is
+                     responsible for writing to only legitimate locations.
+  @param  BufferSize Size of Buffer, must be a multiple of device block size.
+  @param  Buffer     A pointer to the source buffer for the data.
+
+  @retval EFI_SUCCESS           The data was written correctly to the device.
+  @retval EFI_WRITE_PROTECTED   The device can not be written to.
+  @retval EFI_DEVICE_ERROR      The device reported an error while performing the write.
+  @retval EFI_NO_MEDIA          There is no media in the device.
+  @retval EFI_MEDIA_CHNAGED     The MediaId does not matched the current device.
+  @retval EFI_BAD_BUFFER_SIZE   The Buffer was not a multiple of the block size of the device.
+  @retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
+                                or the buffer is not on proper alignment.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoWriteBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL          *This,
+  IN UINT32                         MediaId,
+  IN EFI_LBA                        Lba,
+  IN UINTN                          BufferSize,
+  IN VOID                           *Buffer
+  );
+
+/**
+  Flush the Block Device.
+
+  @param  This              Indicates a pointer to the calling context.
+
+  @retval EFI_SUCCESS       All outstanding data was written to the device
+  @retval EFI_DEVICE_ERROR  The device reported an error while writting back the data
+  @retval EFI_NO_MEDIA      There is no media in the device.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoFlushBlocks (
+  IN EFI_BLOCK_IO_PROTOCOL  *This
+  );
+
+/**
+  Reset the block device hardware.
+
+  @param[in]  This                 Indicates a pointer to the calling context.
+  @param[in]  ExtendedVerification Not used.
+
+  @retval EFI_SUCCESS          The device was reset.
+
+**/
+EFI_STATUS
+EFIAPI
+XenPvBlkDxeBlockIoReset (
+  IN EFI_BLOCK_IO_PROTOCOL   *This,
+  IN BOOLEAN                 ExtendedVerification
+  );
+
+extern EFI_BLOCK_IO_MEDIA  gXenPvBlkDxeBlockIoMedia;
+extern EFI_BLOCK_IO_PROTOCOL  gXenPvBlkDxeBlockIo;
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
index a732a04..f7c3ab9 100644
--- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c
@@ -277,6 +277,7 @@ XenPvBlkDxeDriverBindingStart (
   EFI_STATUS Status;
   XENBUS_PROTOCOL *XenBusIo;
   XEN_BLOCK_FRONT_DEVICE *Dev;
+  EFI_BLOCK_IO_MEDIA *Media;
 
   Status = gBS->OpenProtocol (
                 ControllerHandle,
@@ -295,8 +296,45 @@ XenPvBlkDxeDriverBindingStart (
     goto CloseProtocol;
   }
 
+  CopyMem (&Dev->BlockIo, &gXenPvBlkDxeBlockIo, sizeof (EFI_BLOCK_IO_PROTOCOL));
+  Media = AllocateCopyPool (sizeof (EFI_BLOCK_IO_MEDIA),
+                            &gXenPvBlkDxeBlockIoMedia);
+  if (Dev->MediaInfo.VDiskInfo & VDISK_REMOVABLE) {
+    Media->RemovableMedia = TRUE;
+  }
+  Media->MediaPresent = TRUE;
+  Media->ReadOnly = !Dev->MediaInfo.ReadWrite;
+  if (Dev->MediaInfo.CdRom) {
+    //
+    // If it's a cdrom, the blocksize value need to be 2048 for OVMF to
+    // recognize it as a cdrom:
+    //    MdeModulePkg/Universal/Disk/PartitionDxe/ElTorito.c
+    //
+    Media->BlockSize = 2048;
+    Media->LastBlock = DivU64x32 (Dev->MediaInfo.Sectors,
+                                  Media->BlockSize / Dev->MediaInfo.SectorSize) - 1;
+  } else {
+    Media->BlockSize = Dev->MediaInfo.SectorSize;
+    Media->LastBlock = Dev->MediaInfo.Sectors - 1;
+  }
+  ASSERT (Media->BlockSize % 512 == 0);
+  Dev->BlockIo.Media = Media;
+
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                    &ControllerHandle,
+                    &gEfiBlockIoProtocolGuid, &Dev->BlockIo,
+                    NULL
+                    );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((EFI_D_ERROR, "XenPvBlk: install protocol fail: %r\n", Status));
+    goto UninitBlockFront;
+  }
+
   return EFI_SUCCESS;
 
+UninitBlockFront:
+  FreePool (Media);
+  XenPvBlockFrontShutdown (Dev);
 CloseProtocol:
   gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
                       This->DriverBindingHandle, ControllerHandle);
@@ -338,6 +376,33 @@ XenPvBlkDxeDriverBindingStop (
   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
   )
 {
+  EFI_BLOCK_IO_PROTOCOL *BlockIo;
+  XEN_BLOCK_FRONT_DEVICE *Dev;
+  EFI_BLOCK_IO_MEDIA *Media;
+  EFI_STATUS Status;
+
+  Status = gBS->OpenProtocol (
+                  ControllerHandle, &gEfiBlockIoProtocolGuid,
+                  (VOID **)&BlockIo,
+                  This->DriverBindingHandle, ControllerHandle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->UninstallProtocolInterface (ControllerHandle,
+                  &gEfiBlockIoProtocolGuid, BlockIo);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Media = BlockIo->Media;
+  Dev = XEN_BLOCK_FRONT_FROM_BLOCK_IO (BlockIo);
+  XenPvBlockFrontShutdown (Dev);
+
+  FreePool (Media);
+
   gBS->CloseProtocol (ControllerHandle, &gXenBusProtocolGuid,
          This->DriverBindingHandle, ControllerHandle);
 
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
index 5351a96..a94c83d 100644
--- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.h
@@ -93,6 +93,7 @@ extern EFI_COMPONENT_NAME_PROTOCOL  gXenPvBlkDxeComponentName;
 //
 #include "DriverBinding.h"
 #include "ComponentName.h"
+#include "BlockIo.h"
 
 
 #endif
diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
index 9a6e17b..235cfe5 100644
--- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
+++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
@@ -52,6 +52,8 @@
   ComponentName.h
   BlockFront.c
   BlockFront.h
+  BlockIo.c
+  BlockIo.h
 
 
 [LibraryClasses]
-- 
Anthony PERARD

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

* Re: [edk2] [PATCH v3 03/19] OvmfPkg: Add basic skeleton for the XenBus bus driver.
       [not found] ` <1413565442-29149-4-git-send-email-anthony.perard@citrix.com>
@ 2014-10-19 23:27   ` Jordan Justen
       [not found]   ` <20141019232711.22698.47223@jljusten-ivy>
  1 sibling, 0 replies; 29+ messages in thread
From: Jordan Justen @ 2014-10-19 23:27 UTC (permalink / raw)
  To: edk2-devel, Anthony PERARD; +Cc: Xen Devel

On 2014-10-17 10:03:46, Anthony PERARD wrote:
> This includes Component Name and Driver Binding.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> 
> ---
> Change in V3:
> - enable compilation for Ia32 and Ia32X64
> - fix version (driver binding)
> 
> Change in V2:
> - Simple support of controller name.
> - Cleaning up comments, files header.
> - Add Licenses
> - Rename XenbusDxe to XenBusDxe.
> ---
>  OvmfPkg/OvmfPkgIa32.dsc           |   1 +
>  OvmfPkg/OvmfPkgIa32.fdf           |   1 +
>  OvmfPkg/OvmfPkgIa32X64.dsc        |   1 +
>  OvmfPkg/OvmfPkgIa32X64.fdf        |   1 +
>  OvmfPkg/OvmfPkgX64.dsc            |   1 +
>  OvmfPkg/OvmfPkgX64.fdf            |   1 +
>  OvmfPkg/XenBusDxe/ComponentName.c | 190 +++++++++++++++++++++++
>  OvmfPkg/XenBusDxe/ComponentName.h | 110 +++++++++++++
>  OvmfPkg/XenBusDxe/DriverBinding.h | 144 +++++++++++++++++
>  OvmfPkg/XenBusDxe/XenBusDxe.c     | 317 ++++++++++++++++++++++++++++++++++++++
>  OvmfPkg/XenBusDxe/XenBusDxe.h     |  93 +++++++++++
>  OvmfPkg/XenBusDxe/XenBusDxe.inf   |  56 +++++++
>  12 files changed, 916 insertions(+)
>  create mode 100644 OvmfPkg/XenBusDxe/ComponentName.c
>  create mode 100644 OvmfPkg/XenBusDxe/ComponentName.h
>  create mode 100644 OvmfPkg/XenBusDxe/DriverBinding.h
>  create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.c
>  create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.h
>  create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.inf

> diff --git a/OvmfPkg/XenBusDxe/ComponentName.c b/OvmfPkg/XenBusDxe/ComponentName.c
> new file mode 100644
> index 0000000..bcf1e51
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/ComponentName.c
> @@ -0,0 +1,190 @@
> +/** @file
> +  Component Name functions implementation for XenBus Bus driver.
> +
> +  Copyright (C) 2014, Citrix Ltd.
> +
> +  Redistribution and use in source and binary forms, with or without
> +  modification, are permitted provided that the following conditions
> +  are met:
> +
> +  * Redistributions of source code must retain the above copyright
> +    notice, this list of conditions and the following disclaimer.
> +  * Redistributions in binary form must reproduce the above copyright
> +    notice, this list of conditions and the following disclaimer in
> +    the documentation and/or other materials provided with the
> +    distribution.
> +
> +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> +  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> +  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> +  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> +  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> +  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
> +  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> +  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
> +  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +  POSSIBILITY OF SUCH DAMAGE.

This appears to match the 2-clause BSD license like the rest of EDK
II. Any reason to not follow the commonly used file header text?
"""
  This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
  which accompanies this distribution.  The full text of the license may be found at
  http://opensource.org/licenses/bsd-license.php

  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
"""

> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> new file mode 100644
> index 0000000..25fd2f6
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> @@ -0,0 +1,56 @@
> +
> +## @file
> +#  TODO: Brief Description of UEFI Driver XenBusDxe
> +#
> +#  TODO: Detailed Description of UEFI Driver XenBusDxe
> +#
> +#  TODO: Copyright for UEFI Driver XenBusDxe
> +#
> +#  TODO: License for UEFI Driver XenBusDxe

It looks like this is still todo by the end of the series.

-Jordan

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

* Re: [edk2] [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project.
       [not found] ` <1413565442-29149-3-git-send-email-anthony.perard@citrix.com>
@ 2014-10-19 23:47   ` Jordan Justen
       [not found]   ` <20141019234732.22698.78740@jljusten-ivy>
  1 sibling, 0 replies; 29+ messages in thread
From: Jordan Justen @ 2014-10-19 23:47 UTC (permalink / raw)
  To: edk2-devel, Anthony PERARD; +Cc: Xen Devel

On 2014-10-17 10:03:45, Anthony PERARD wrote:
> This patch imports publics headers in order to use features from Xen
> like XenStore, PV Block... There is only the necessary header files and
> there are only a few modifications in order to facilitate future merge of
> more recent header (that would be necessary to access new features).
> 
> There is little modification compared to the original files:
> - Removed most of the unused part of the headers
> - Use of ZeroMem() instead of memset()
> - using #pragma pack(4) for IA32 compilation.

Usually EDK II uses pack(1) when concerned about structure layout. I'm
not saying you need to change this, but it does stand out.

> - Replace types to be more UEFI compliant using a script.
> 
> OVMF, when built for IA32 arch, uses the gcc switch -malign-double. This
> change the alignment of fields in some struct compare to what is
> espected by Xen and any backends. To fix the alignment, the #pragma pack(4)
> directive is used around the struct that need it.
> 
> Command to run to change types:
> find OvmfPkg/Include/IndustryStandard/Xen -type f -name '*.h' -exec sed
>   --regexp-extended --file=fix_type_in_xen_includes.sed --in-place {} \;

Did you intend to include fix_type_in_xen_includes.sed?

Maybe you could mention the source (url, version) for the files? Was
it a direct copy into OvmfPkg/Include/IndustryStandard/Xen before
using the script?

How easy do you think someone could 'update' the files from Xen based
on the information you provided here?

> This line is commented instead of been change as I'm not sure why it
> does not compile (when s/char/CHAR8/), and it does not seems necessary
> so far.
>   /* __DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); */

Could 'unsigned char' => 'UINT8' help?

-Jordan

>   in OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
> 
> Avoid changing the 'long' that is not a type (with the first line).
> $ cat fix_type_in_xen_includes.sed
> /as long as/b
> 
> s/([^a-zA-Z0-9_]|^)uint8_t([^a-zA-Z0-9_]|$)/\1UINT8\2/g
> s/([^a-zA-Z0-9_]|^)uint16_t([^a-zA-Z0-9_]|$)/\1UINT16\2/g
> s/([^a-zA-Z0-9_]|^)uint32_t([^a-zA-Z0-9_]|$)/\1UINT32\2/g
> s/([^a-zA-Z0-9_]|^)uint64_t([^a-zA-Z0-9_]|$)/\1UINT64\2/g
> 
> s/([^a-zA-Z0-9_]|^)int8_t([^a-zA-Z0-9_]|$)/\1INT8\2/g
> s/([^a-zA-Z0-9_]|^)int16_t([^a-zA-Z0-9_]|$)/\1INT16\2/g
> s/([^a-zA-Z0-9_]|^)int32_t([^a-zA-Z0-9_]|$)/\1INT32\2/g
> s/([^a-zA-Z0-9_]|^)int64_t([^a-zA-Z0-9_]|$)/\1INT64\2/g
> 
> s/([^a-zA-Z0-9_]|^)void([^a-zA-Z0-9_]|$)/\1VOID\2/g
> s/([^a-zA-Z0-9_]|^)unsigned int([^a-zA-Z0-9_]|$)/\1UINT32\2/g
> s/([^a-zA-Z0-9_]|^)int([^a-zA-Z0-9_]|$)/\1INT32\2/g
> s/([^a-zA-Z0-9_]|^)char([^a-zA-Z0-9_]|$)/\1CHAR8\2/g
> s/([^a-zA-Z0-9_]|^)unsigned long([^a-zA-Z0-9_]|$)/\1UINTN\2/g
> s/([^a-zA-Z0-9_]|^)long([^a-zA-Z0-9_]|$)/\1INTN\2/g
> 
> License: This patch adds many files under the MIT licence.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> 
> ---
> Change in V3:
> - Remove unused header sched.h
> - moving xs_wire.h in a later patch, where it's first needed
> - moving io/blkif.h in a later patch (XenPvBlkDxe: Add BlockFront client)
> - moving event_channel.h in a later patch (XenBusDxe: Add Event Channel Notify)
> - using #pragma pack(4) for IA32
> - headers trimed down, removed most of the unused struct/define/...
> ---
>  .../IndustryStandard/Xen/arch-x86/xen-x86_32.h     |  59 +++
>  .../IndustryStandard/Xen/arch-x86/xen-x86_64.h     |  59 +++
>  .../Include/IndustryStandard/Xen/arch-x86/xen.h    | 112 ++++++
>  OvmfPkg/Include/IndustryStandard/Xen/grant_table.h | 444 +++++++++++++++++++++
>  OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h  |  37 ++
>  OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h  | 150 +++++++
>  .../Include/IndustryStandard/Xen/io/protocols.h    |  40 ++
>  OvmfPkg/Include/IndustryStandard/Xen/io/ring.h     | 312 +++++++++++++++
>  OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h   |  80 ++++
>  OvmfPkg/Include/IndustryStandard/Xen/memory.h      |  94 +++++
>  OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h  |  44 ++
>  OvmfPkg/Include/IndustryStandard/Xen/xen.h         | 341 ++++++++++++++++
>  12 files changed, 1772 insertions(+)
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/grant_table.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/ring.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/memory.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Xen/xen.h
> 
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h
> new file mode 100644
> index 0000000..ed7e12b
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_32.h
> @@ -0,0 +1,59 @@
> +/******************************************************************************
> + * xen-x86_32.h
> + * 
> + * Guest OS interface to x86 32-bit Xen.
> + * 
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (c) 2004-2007, K A Fraser
> + */
> +
> +#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
> +#define __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__
> +
> +/*
> + * Hypercall interface:
> + *  Input:  %ebx, %ecx, %edx, %esi, %edi, %ebp (arguments 1-6)
> + *  Output: %eax
> + * Access is via hypercall page (set up by guest loader or via a Xen MSR):
> + *  call hypercall_page + hypercall-number * 32
> + * Clobbered: Argument registers (e.g., 2-arg hypercall clobbers %ebx,%ecx)
> + */
> +
> +#ifndef __ASSEMBLY__
> +
> +struct arch_vcpu_info {
> +    UINTN cr2;
> +    UINTN pad[5]; /* sizeof(vcpu_info_t) == 64 */
> +};
> +typedef struct arch_vcpu_info arch_vcpu_info_t;
> +
> +#endif /* !__ASSEMBLY__ */
> +
> +#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_32_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h
> new file mode 100644
> index 0000000..c5ef5d4
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen-x86_64.h
> @@ -0,0 +1,59 @@
> +/******************************************************************************
> + * xen-x86_64.h
> + * 
> + * Guest OS interface to x86 64-bit Xen.
> + * 
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (c) 2004-2006, K A Fraser
> + */
> +
> +#ifndef __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
> +#define __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__
> +
> +/*
> + * Hypercall interface:
> + *  Input:  %rdi, %rsi, %rdx, %r10, %r8, %r9 (arguments 1-6)
> + *  Output: %rax
> + * Access is via hypercall page (set up by guest loader or via a Xen MSR):
> + *  call hypercall_page + hypercall-number * 32
> + * Clobbered: argument registers (e.g., 2-arg hypercall clobbers %rdi,%rsi)
> + */
> +
> +#ifndef __ASSEMBLY__
> +
> +struct arch_vcpu_info {
> +    UINTN cr2;
> +    UINTN pad; /* sizeof(vcpu_info_t) == 64 */
> +};
> +typedef struct arch_vcpu_info arch_vcpu_info_t;
> +
> +#endif /* !__ASSEMBLY__ */
> +
> +#endif /* __XEN_PUBLIC_ARCH_X86_XEN_X86_64_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
> new file mode 100644
> index 0000000..951d57b
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
> @@ -0,0 +1,112 @@
> +/******************************************************************************
> + * arch-x86/xen.h
> + * 
> + * Guest OS interface to x86 Xen.
> + * 
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (c) 2004-2006, K A Fraser
> + */
> +
> +#include "../xen.h"
> +
> +#ifndef __XEN_PUBLIC_ARCH_X86_XEN_H__
> +#define __XEN_PUBLIC_ARCH_X86_XEN_H__
> +
> +/* Structural guest handles introduced in 0x00030201. */
> +#if __XEN_INTERFACE_VERSION__ >= 0x00030201
> +#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
> +    typedef struct { type *p; } __guest_handle_ ## name
> +#else
> +#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
> +    typedef type * __guest_handle_ ## name
> +#endif
> +
> +/*
> + * XEN_GUEST_HANDLE represents a guest pointer, when passed as a field
> + * in a struct in memory.
> + * XEN_GUEST_HANDLE_PARAM represent a guest pointer, when passed as an
> + * hypercall argument.
> + * XEN_GUEST_HANDLE_PARAM and XEN_GUEST_HANDLE are the same on X86 but
> + * they might not be on other architectures.
> + */
> +#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
> +    ___DEFINE_XEN_GUEST_HANDLE(name, type);   \
> +    ___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
> +#define DEFINE_XEN_GUEST_HANDLE(name)   __DEFINE_XEN_GUEST_HANDLE(name, name)
> +#define __XEN_GUEST_HANDLE(name)        __guest_handle_ ## name
> +#define XEN_GUEST_HANDLE(name)          __XEN_GUEST_HANDLE(name)
> +#define XEN_GUEST_HANDLE_PARAM(name)    XEN_GUEST_HANDLE(name)
> +#define set_xen_guest_handle_raw(hnd, val)  do { (hnd).p = val; } while (0)
> +#ifdef __XEN_TOOLS__
> +#define get_xen_guest_handle(val, hnd)  do { val = (hnd).p; } while (0)
> +#endif
> +#define set_xen_guest_handle(hnd, val) set_xen_guest_handle_raw(hnd, val)
> +
> +#if defined(__i386__)
> +#include "xen-x86_32.h"
> +#elif defined(__x86_64__)
> +#include "xen-x86_64.h"
> +#endif
> +
> +#ifndef __ASSEMBLY__
> +typedef UINTN xen_pfn_t;
> +#define PRI_xen_pfn "lx"
> +#endif
> +
> +#define XEN_HAVE_PV_UPCALL_MASK 1
> +
> +/* Maximum number of virtual CPUs in legacy multi-processor guests. */
> +#define XEN_LEGACY_MAX_VCPUS 32
> +
> +#ifndef __ASSEMBLY__
> +
> +typedef UINTN xen_ulong_t;
> +#define PRI_xen_ulong "lx"
> +
> +typedef UINT64 tsc_timestamp_t; /* RDTSC timestamp */
> +
> +#ifdef __i386__
> +#pragma pack(4)
> +#endif
> +struct arch_shared_info {
> +    UINTN max_pfn;                  /* max pfn that appears in table */
> +    /* Frame containing list of mfns containing list of mfns containing p2m. */
> +    xen_pfn_t     pfn_to_mfn_frame_list_list;
> +    UINTN nmi_reason;
> +    UINT64 pad[32];
> +};
> +typedef struct arch_shared_info arch_shared_info_t;
> +#ifdef __i386__
> +#pragma pack()
> +#endif
> +
> +#endif /* !__ASSEMBLY__ */
> +
> +#endif /* __XEN_PUBLIC_ARCH_X86_XEN_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/grant_table.h b/OvmfPkg/Include/IndustryStandard/Xen/grant_table.h
> new file mode 100644
> index 0000000..8725931
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/grant_table.h
> @@ -0,0 +1,444 @@
> +/******************************************************************************
> + * grant_table.h
> + *
> + * Interface for granting foreign access to page frames, and receiving
> + * page-ownership transfers.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (c) 2004, K A Fraser
> + */
> +
> +#ifndef __XEN_PUBLIC_GRANT_TABLE_H__
> +#define __XEN_PUBLIC_GRANT_TABLE_H__
> +
> +#include "xen.h"
> +
> +/*
> + * `incontents 150 gnttab Grant Tables
> + *
> + * Xen's grant tables provide a generic mechanism to memory sharing
> + * between domains. This shared memory interface underpins the split
> + * device drivers for block and network IO.
> + *
> + * Each domain has its own grant table. This is a data structure that
> + * is shared with Xen; it allows the domain to tell Xen what kind of
> + * permissions other domains have on its pages. Entries in the grant
> + * table are identified by grant references. A grant reference is an
> + * integer, which indexes into the grant table. It acts as a
> + * capability which the grantee can use to perform operations on the
> + * granter’s memory.
> + *
> + * This capability-based system allows shared-memory communications
> + * between unprivileged domains. A grant reference also encapsulates
> + * the details of a shared page, removing the need for a domain to
> + * know the real machine address of a page it is sharing. This makes
> + * it possible to share memory correctly with domains running in
> + * fully virtualised memory.
> + */
> +
> +/***********************************
> + * GRANT TABLE REPRESENTATION
> + */
> +
> +/* Some rough guidelines on accessing and updating grant-table entries
> + * in a concurrency-safe manner. For more information, Linux contains a
> + * reference implementation for guest OSes (drivers/xen/grant_table.c, see
> + * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/xen/grant-table.c;hb=HEAD
> + *
> + * NB. WMB is a no-op on current-generation x86 processors. However, a
> + *     compiler barrier will still be required.
> + *
> + * Introducing a valid entry into the grant table:
> + *  1. Write ent->domid.
> + *  2. Write ent->frame:
> + *      GTF_permit_access:   Frame to which access is permitted.
> + *      GTF_accept_transfer: Pseudo-phys frame slot being filled by new
> + *                           frame, or zero if none.
> + *  3. Write memory barrier (WMB).
> + *  4. Write ent->flags, inc. valid type.
> + *
> + * Invalidating an unused GTF_permit_access entry:
> + *  1. flags = ent->flags.
> + *  2. Observe that !(flags & (GTF_reading|GTF_writing)).
> + *  3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
> + *  NB. No need for WMB as reuse of entry is control-dependent on success of
> + *      step 3, and all architectures guarantee ordering of ctrl-dep writes.
> + *
> + * Invalidating an in-use GTF_permit_access entry:
> + *  This cannot be done directly. Request assistance from the domain controller
> + *  which can set a timeout on the use of a grant entry and take necessary
> + *  action. (NB. This is not yet implemented!).
> + *
> + * Invalidating an unused GTF_accept_transfer entry:
> + *  1. flags = ent->flags.
> + *  2. Observe that !(flags & GTF_transfer_committed). [*]
> + *  3. Check result of SMP-safe CMPXCHG(&ent->flags, flags, 0).
> + *  NB. No need for WMB as reuse of entry is control-dependent on success of
> + *      step 3, and all architectures guarantee ordering of ctrl-dep writes.
> + *  [*] If GTF_transfer_committed is set then the grant entry is 'committed'.
> + *      The guest must /not/ modify the grant entry until the address of the
> + *      transferred frame is written. It is safe for the guest to spin waiting
> + *      for this to occur (detect by observing GTF_transfer_completed in
> + *      ent->flags).
> + *
> + * Invalidating a committed GTF_accept_transfer entry:
> + *  1. Wait for (ent->flags & GTF_transfer_completed).
> + *
> + * Changing a GTF_permit_access from writable to read-only:
> + *  Use SMP-safe CMPXCHG to set GTF_readonly, while checking !GTF_writing.
> + *
> + * Changing a GTF_permit_access from read-only to writable:
> + *  Use SMP-safe bit-setting instruction.
> + */
> +
> +/*
> + * Reference to a grant entry in a specified domain's grant table.
> + */
> +typedef UINT32 grant_ref_t;
> +
> +/*
> + * A grant table comprises a packed array of grant entries in one or more
> + * page frames shared between Xen and a guest.
> + * [XEN]: This field is written by Xen and read by the sharing guest.
> + * [GST]: This field is written by the guest and read by Xen.
> + */
> +
> +/*
> + * Version 1 of the grant table entry structure is maintained purely
> + * for backwards compatibility.  New guests should use version 2.
> + */
> +#if __XEN_INTERFACE_VERSION__ < 0x0003020a
> +#define grant_entry_v1 grant_entry
> +#define grant_entry_v1_t grant_entry_t
> +#endif
> +struct grant_entry_v1 {
> +    /* GTF_xxx: various type and flag information.  [XEN,GST] */
> +    UINT16 flags;
> +    /* The domain being granted foreign privileges. [GST] */
> +    domid_t  domid;
> +    /*
> +     * GTF_permit_access: Frame that @domid is allowed to map and access. [GST]
> +     * GTF_accept_transfer: Frame whose ownership transferred by @domid. [XEN]
> +     */
> +    UINT32 frame;
> +};
> +typedef struct grant_entry_v1 grant_entry_v1_t;
> +
> +/* The first few grant table entries will be preserved across grant table
> + * version changes and may be pre-populated at domain creation by tools.
> + */
> +#define GNTTAB_NR_RESERVED_ENTRIES     8
> +#define GNTTAB_RESERVED_CONSOLE        0
> +#define GNTTAB_RESERVED_XENSTORE       1
> +
> +/*
> + * Type of grant entry.
> + *  GTF_invalid: This grant entry grants no privileges.
> + *  GTF_permit_access: Allow @domid to map/access @frame.
> + *  GTF_accept_transfer: Allow @domid to transfer ownership of one page frame
> + *                       to this guest. Xen writes the page number to @frame.
> + *  GTF_transitive: Allow @domid to transitively access a subrange of
> + *                  @trans_grant in @trans_domid.  No mappings are allowed.
> + */
> +#define GTF_invalid         (0U<<0)
> +#define GTF_permit_access   (1U<<0)
> +#define GTF_accept_transfer (2U<<0)
> +#define GTF_transitive      (3U<<0)
> +#define GTF_type_mask       (3U<<0)
> +
> +/*
> + * Subflags for GTF_permit_access.
> + *  GTF_readonly: Restrict @domid to read-only mappings and accesses. [GST]
> + *  GTF_reading: Grant entry is currently mapped for reading by @domid. [XEN]
> + *  GTF_writing: Grant entry is currently mapped for writing by @domid. [XEN]
> + *  GTF_PAT, GTF_PWT, GTF_PCD: (x86) cache attribute flags for the grant [GST]
> + *  GTF_sub_page: Grant access to only a subrange of the page.  @domid
> + *                will only be allowed to copy from the grant, and not
> + *                map it. [GST]
> + */
> +#define _GTF_readonly       (2)
> +#define GTF_readonly        (1U<<_GTF_readonly)
> +#define _GTF_reading        (3)
> +#define GTF_reading         (1U<<_GTF_reading)
> +#define _GTF_writing        (4)
> +#define GTF_writing         (1U<<_GTF_writing)
> +#define _GTF_PWT            (5)
> +#define GTF_PWT             (1U<<_GTF_PWT)
> +#define _GTF_PCD            (6)
> +#define GTF_PCD             (1U<<_GTF_PCD)
> +#define _GTF_PAT            (7)
> +#define GTF_PAT             (1U<<_GTF_PAT)
> +#define _GTF_sub_page       (8)
> +#define GTF_sub_page        (1U<<_GTF_sub_page)
> +
> +/*
> + * Subflags for GTF_accept_transfer:
> + *  GTF_transfer_committed: Xen sets this flag to indicate that it is committed
> + *      to transferring ownership of a page frame. When a guest sees this flag
> + *      it must /not/ modify the grant entry until GTF_transfer_completed is
> + *      set by Xen.
> + *  GTF_transfer_completed: It is safe for the guest to spin-wait on this flag
> + *      after reading GTF_transfer_committed. Xen will always write the frame
> + *      address, followed by ORing this flag, in a timely manner.
> + */
> +#define _GTF_transfer_committed (2)
> +#define GTF_transfer_committed  (1U<<_GTF_transfer_committed)
> +#define _GTF_transfer_completed (3)
> +#define GTF_transfer_completed  (1U<<_GTF_transfer_completed)
> +
> +/*
> + * Version 2 grant table entries.  These fulfil the same role as
> + * version 1 entries, but can represent more complicated operations.
> + * Any given domain will have either a version 1 or a version 2 table,
> + * and every entry in the table will be the same version.
> + *
> + * The interface by which domains use grant references does not depend
> + * on the grant table version in use by the other domain.
> + */
> +#if __XEN_INTERFACE_VERSION__ >= 0x0003020a
> +/*
> + * Version 1 and version 2 grant entries share a common prefix.  The
> + * fields of the prefix are documented as part of struct
> + * grant_entry_v1.
> + */
> +struct grant_entry_header {
> +    UINT16 flags;
> +    domid_t  domid;
> +};
> +typedef struct grant_entry_header grant_entry_header_t;
> +
> +/*
> + * Version 2 of the grant entry structure.
> + */
> +union grant_entry_v2 {
> +    grant_entry_header_t hdr;
> +
> +    /*
> +     * This member is used for V1-style full page grants, where either:
> +     *
> +     * -- hdr.type is GTF_accept_transfer, or
> +     * -- hdr.type is GTF_permit_access and GTF_sub_page is not set.
> +     *
> +     * In that case, the frame field has the same semantics as the
> +     * field of the same name in the V1 entry structure.
> +     */
> +    struct {
> +        grant_entry_header_t hdr;
> +        UINT32 pad0;
> +        UINT64 frame;
> +    } full_page;
> +
> +    /*
> +     * If the grant type is GTF_grant_access and GTF_sub_page is set,
> +     * @domid is allowed to access bytes [@page_off,@page_off+@length)
> +     * in frame @frame.
> +     */
> +    struct {
> +        grant_entry_header_t hdr;
> +        UINT16 page_off;
> +        UINT16 length;
> +        UINT64 frame;
> +    } sub_page;
> +
> +    /*
> +     * If the grant is GTF_transitive, @domid is allowed to use the
> +     * grant @gref in domain @trans_domid, as if it was the local
> +     * domain.  Obviously, the transitive access must be compatible
> +     * with the original grant.
> +     *
> +     * The current version of Xen does not allow transitive grants
> +     * to be mapped.
> +     */
> +    struct {
> +        grant_entry_header_t hdr;
> +        domid_t trans_domid;
> +        UINT16 pad0;
> +        grant_ref_t gref;
> +    } transitive;
> +
> +    UINT32 __spacer[4]; /* Pad to a power of two */
> +};
> +typedef union grant_entry_v2 grant_entry_v2_t;
> +
> +typedef UINT16 grant_status_t;
> +
> +#endif /* __XEN_INTERFACE_VERSION__ */
> +
> +/***********************************
> + * GRANT TABLE QUERIES AND USES
> + */
> +
> +/* ` enum neg_errnoval
> + * ` HYPERVISOR_grant_table_op(enum grant_table_op cmd,
> + * `                           VOID *args,
> + * `                           UINT32 count)
> + * `
> + *
> + * @args points to an array of a per-command data structure. The array
> + * has @count members
> + */
> +
> +/* ` enum grant_table_op { // GNTTABOP_* => struct gnttab_* */
> +#define GNTTABOP_map_grant_ref        0
> +#define GNTTABOP_unmap_grant_ref      1
> +/* ` } */
> +
> +/*
> + * Handle to track a mapping created via a grant reference.
> + */
> +typedef UINT32 grant_handle_t;
> +
> +/*
> + * GNTTABOP_map_grant_ref: Map the grant entry (<dom>,<ref>) for access
> + * by devices and/or host CPUs. If successful, <handle> is a tracking number
> + * that must be presented later to destroy the mapping(s). On error, <handle>
> + * is a negative status code.
> + * NOTES:
> + *  1. If GNTMAP_device_map is specified then <dev_bus_addr> is the address
> + *     via which I/O devices may access the granted frame.
> + *  2. If GNTMAP_host_map is specified then a mapping will be added at
> + *     either a host virtual address in the current address space, or at
> + *     a PTE at the specified machine address.  The type of mapping to
> + *     perform is selected through the GNTMAP_contains_pte flag, and the
> + *     address is specified in <host_addr>.
> + *  3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a
> + *     host mapping is destroyed by other means then it is *NOT* guaranteed
> + *     to be accounted to the correct grant reference!
> + */
> +struct gnttab_map_grant_ref {
> +    /* IN parameters. */
> +    UINT64 host_addr;
> +    UINT32 flags;               /* GNTMAP_* */
> +    grant_ref_t ref;
> +    domid_t  dom;
> +    /* OUT parameters. */
> +    INT16  status;              /* => enum grant_status */
> +    grant_handle_t handle;
> +    UINT64 dev_bus_addr;
> +};
> +typedef struct gnttab_map_grant_ref gnttab_map_grant_ref_t;
> +DEFINE_XEN_GUEST_HANDLE(gnttab_map_grant_ref_t);
> +
> +/*
> + * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings
> + * tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that
> + * field is ignored. If non-zero, they must refer to a device/host mapping
> + * that is tracked by <handle>
> + * NOTES:
> + *  1. The call may fail in an undefined manner if either mapping is not
> + *     tracked by <handle>.
> + *  3. After executing a batch of unmaps, it is guaranteed that no stale
> + *     mappings will remain in the device or host TLBs.
> + */
> +struct gnttab_unmap_grant_ref {
> +    /* IN parameters. */
> +    UINT64 host_addr;
> +    UINT64 dev_bus_addr;
> +    grant_handle_t handle;
> +    /* OUT parameters. */
> +    INT16  status;              /* => enum grant_status */
> +};
> +typedef struct gnttab_unmap_grant_ref gnttab_unmap_grant_ref_t;
> +DEFINE_XEN_GUEST_HANDLE(gnttab_unmap_grant_ref_t);
> +
> +/*
> + * Bitfield values for gnttab_map_grant_ref.flags.
> + */
> + /* Map the grant entry for access by I/O devices. */
> +#define _GNTMAP_device_map      (0)
> +#define GNTMAP_device_map       (1<<_GNTMAP_device_map)
> + /* Map the grant entry for access by host CPUs. */
> +#define _GNTMAP_host_map        (1)
> +#define GNTMAP_host_map         (1<<_GNTMAP_host_map)
> + /* Accesses to the granted frame will be restricted to read-only access. */
> +#define _GNTMAP_readonly        (2)
> +#define GNTMAP_readonly         (1<<_GNTMAP_readonly)
> + /*
> +  * GNTMAP_host_map subflag:
> +  *  0 => The host mapping is usable only by the guest OS.
> +  *  1 => The host mapping is usable by guest OS + current application.
> +  */
> +#define _GNTMAP_application_map (3)
> +#define GNTMAP_application_map  (1<<_GNTMAP_application_map)
> +
> + /*
> +  * GNTMAP_contains_pte subflag:
> +  *  0 => This map request contains a host virtual address.
> +  *  1 => This map request contains the machine addess of the PTE to update.
> +  */
> +#define _GNTMAP_contains_pte    (4)
> +#define GNTMAP_contains_pte     (1<<_GNTMAP_contains_pte)
> +
> +#define _GNTMAP_can_fail        (5)
> +#define GNTMAP_can_fail         (1<<_GNTMAP_can_fail)
> +
> +/*
> + * Bits to be placed in guest kernel available PTE bits (architecture
> + * dependent; only supported when XENFEAT_gnttab_map_avail_bits is set).
> + */
> +#define _GNTMAP_guest_avail0    (16)
> +#define GNTMAP_guest_avail_mask ((UINT32)~0 << _GNTMAP_guest_avail0)
> +
> +/*
> + * Values for error status returns. All errors are -ve.
> + */
> +/* ` enum grant_status { */
> +#define GNTST_okay             (0)  /* Normal return.                        */
> +#define GNTST_general_error    (-1) /* General undefined error.              */
> +#define GNTST_bad_domain       (-2) /* Unrecognsed domain id.                */
> +#define GNTST_bad_gntref       (-3) /* Unrecognised or inappropriate gntref. */
> +#define GNTST_bad_handle       (-4) /* Unrecognised or inappropriate handle. */
> +#define GNTST_bad_virt_addr    (-5) /* Inappropriate virtual address to map. */
> +#define GNTST_bad_dev_addr     (-6) /* Inappropriate device address to unmap.*/
> +#define GNTST_no_device_space  (-7) /* Out of space in I/O MMU.              */
> +#define GNTST_permission_denied (-8) /* Not enough privilege for operation.  */
> +#define GNTST_bad_page         (-9) /* Specified page was invalid for op.    */
> +#define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary.   */
> +#define GNTST_address_too_big (-11) /* transfer page address too large.      */
> +#define GNTST_eagain          (-12) /* Operation not done; try again.        */
> +/* ` } */
> +
> +#define GNTTABOP_error_msgs {                   \
> +    "okay",                                     \
> +    "undefined error",                          \
> +    "unrecognised domain id",                   \
> +    "invalid grant reference",                  \
> +    "invalid mapping handle",                   \
> +    "invalid virtual address",                  \
> +    "invalid device address",                   \
> +    "no spare translation slot in the I/O MMU", \
> +    "permission denied",                        \
> +    "bad page",                                 \
> +    "copy arguments cross page boundary",       \
> +    "page address size too large",              \
> +    "operation not done; try again"             \
> +}
> +
> +#endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h b/OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h
> new file mode 100644
> index 0000000..120f62f
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/hvm/hvm_op.h
> @@ -0,0 +1,37 @@
> +/*
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef __XEN_PUBLIC_HVM_HVM_OP_H__
> +#define __XEN_PUBLIC_HVM_HVM_OP_H__
> +
> +#include "../xen.h"
> +
> +/* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
> +#define HVMOP_set_param           0
> +#define HVMOP_get_param           1
> +struct xen_hvm_param {
> +    domid_t  domid;    /* IN */
> +    UINT32 index;    /* IN */
> +    UINT64 value;    /* IN/OUT */
> +};
> +typedef struct xen_hvm_param xen_hvm_param_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_param_t);
> +
> +#endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h b/OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h
> new file mode 100644
> index 0000000..517a184
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/hvm/params.h
> @@ -0,0 +1,150 @@
> +/*
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef __XEN_PUBLIC_HVM_PARAMS_H__
> +#define __XEN_PUBLIC_HVM_PARAMS_H__
> +
> +#include "hvm_op.h"
> +
> +/*
> + * Parameter space for HVMOP_{set,get}_param.
> + */
> +
> +/*
> + * How should CPU0 event-channel notifications be delivered?
> + * val[63:56] == 0: val[55:0] is a delivery GSI (Global System Interrupt).
> + * val[63:56] == 1: val[55:0] is a delivery PCI INTx line, as follows:
> + *                  Domain = val[47:32], Bus  = val[31:16],
> + *                  DevFn  = val[15: 8], IntX = val[ 1: 0]
> + * val[63:56] == 2: val[7:0] is a vector number, check for
> + *                  XENFEAT_hvm_callback_vector to know if this delivery
> + *                  method is available.
> + * If val == 0 then CPU0 event-channel notifications are not delivered.
> + */
> +#define HVM_PARAM_CALLBACK_IRQ 0
> +
> +/*
> + * These are not used by Xen. They are here for convenience of HVM-guest
> + * xenbus implementations.
> + */
> +#define HVM_PARAM_STORE_PFN    1
> +#define HVM_PARAM_STORE_EVTCHN 2
> +
> +#define HVM_PARAM_PAE_ENABLED  4
> +
> +#define HVM_PARAM_IOREQ_PFN    5
> +
> +#define HVM_PARAM_BUFIOREQ_PFN 6
> +#define HVM_PARAM_BUFIOREQ_EVTCHN 26
> +
> +#if defined(__i386__) || defined(__x86_64__)
> +
> +/* Expose Viridian interfaces to this HVM guest? */
> +#define HVM_PARAM_VIRIDIAN     9
> +
> +#endif
> +
> +/*
> + * Set mode for virtual timers (currently x86 only):
> + *  delay_for_missed_ticks (default):
> + *   Do not advance a vcpu's time beyond the correct delivery time for
> + *   interrupts that have been missed due to preemption. Deliver missed
> + *   interrupts when the vcpu is rescheduled and advance the vcpu's virtual
> + *   time stepwise for each one.
> + *  no_delay_for_missed_ticks:
> + *   As above, missed interrupts are delivered, but guest time always tracks
> + *   wallclock (i.e., real) time while doing so.
> + *  no_missed_ticks_pending:
> + *   No missed interrupts are held pending. Instead, to ensure ticks are
> + *   delivered at some non-zero rate, if we detect missed ticks then the
> + *   internal tick alarm is not disabled if the VCPU is preempted during the
> + *   next tick period.
> + *  one_missed_tick_pending:
> + *   Missed interrupts are collapsed together and delivered as one 'late tick'.
> + *   Guest time always tracks wallclock (i.e., real) time.
> + */
> +#define HVM_PARAM_TIMER_MODE   10
> +#define HVMPTM_delay_for_missed_ticks    0
> +#define HVMPTM_no_delay_for_missed_ticks 1
> +#define HVMPTM_no_missed_ticks_pending   2
> +#define HVMPTM_one_missed_tick_pending   3
> +
> +/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */
> +#define HVM_PARAM_HPET_ENABLED 11
> +
> +/* Identity-map page directory used by Intel EPT when CR0.PG=0. */
> +#define HVM_PARAM_IDENT_PT     12
> +
> +/* Device Model domain, defaults to 0. */
> +#define HVM_PARAM_DM_DOMAIN    13
> +
> +/* ACPI S state: currently support S0 and S3 on x86. */
> +#define HVM_PARAM_ACPI_S_STATE 14
> +
> +/* TSS used on Intel when CR0.PE=0. */
> +#define HVM_PARAM_VM86_TSS     15
> +
> +/* Boolean: Enable aligning all periodic vpts to reduce interrupts */
> +#define HVM_PARAM_VPT_ALIGN    16
> +
> +/* Console debug shared memory ring and event channel */
> +#define HVM_PARAM_CONSOLE_PFN    17
> +#define HVM_PARAM_CONSOLE_EVTCHN 18
> +
> +/*
> + * Select location of ACPI PM1a and TMR control blocks. Currently two locations
> + * are supported, specified by version 0 or 1 in this parameter:
> + *   - 0: default, use the old addresses
> + *        PM1A_EVT == 0x1f40; PM1A_CNT == 0x1f44; PM_TMR == 0x1f48
> + *   - 1: use the new default qemu addresses
> + *        PM1A_EVT == 0xb000; PM1A_CNT == 0xb004; PM_TMR == 0xb008
> + * You can find these address definitions in <hvm/ioreq.h>
> + */
> +#define HVM_PARAM_ACPI_IOPORTS_LOCATION 19
> +
> +/* Enable blocking memory events, async or sync (pause vcpu until response) 
> + * onchangeonly indicates messages only on a change of value */
> +#define HVM_PARAM_MEMORY_EVENT_CR0          20
> +#define HVM_PARAM_MEMORY_EVENT_CR3          21
> +#define HVM_PARAM_MEMORY_EVENT_CR4          22
> +#define HVM_PARAM_MEMORY_EVENT_INT3         23
> +#define HVM_PARAM_MEMORY_EVENT_SINGLE_STEP  25
> +#define HVM_PARAM_MEMORY_EVENT_MSR          30
> +
> +#define HVMPME_MODE_MASK       (3 << 0)
> +#define HVMPME_mode_disabled   0
> +#define HVMPME_mode_async      1
> +#define HVMPME_mode_sync       2
> +#define HVMPME_onchangeonly    (1 << 2)
> +
> +/* Boolean: Enable nestedhvm (hvm only) */
> +#define HVM_PARAM_NESTEDHVM    24
> +
> +/* Params for the mem event rings */
> +#define HVM_PARAM_PAGING_RING_PFN   27
> +#define HVM_PARAM_ACCESS_RING_PFN   28
> +#define HVM_PARAM_SHARING_RING_PFN  29
> +
> +/* SHUTDOWN_* action in case of a triple fault */
> +#define HVM_PARAM_TRIPLE_FAULT_REASON 31
> +
> +#define HVM_NR_PARAMS          32
> +
> +#endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h b/OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h
> new file mode 100644
> index 0000000..80b196b
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/io/protocols.h
> @@ -0,0 +1,40 @@
> +/******************************************************************************
> + * protocols.h
> + * 
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef __XEN_PROTOCOLS_H__
> +#define __XEN_PROTOCOLS_H__
> +
> +#define XEN_IO_PROTO_ABI_X86_32     "x86_32-abi"
> +#define XEN_IO_PROTO_ABI_X86_64     "x86_64-abi"
> +#define XEN_IO_PROTO_ABI_ARM        "arm-abi"
> +
> +#if defined(__i386__)
> +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_32
> +#elif defined(__x86_64__)
> +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_X86_64
> +#elif defined(__arm__) || defined(__aarch64__)
> +# define XEN_IO_PROTO_ABI_NATIVE XEN_IO_PROTO_ABI_ARM
> +#else
> +# error arch fixup needed here
> +#endif
> +
> +#endif
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/ring.h b/OvmfPkg/Include/IndustryStandard/Xen/io/ring.h
> new file mode 100644
> index 0000000..a8e9ea0
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/io/ring.h
> @@ -0,0 +1,312 @@
> +/******************************************************************************
> + * ring.h
> + * 
> + * Shared producer-consumer ring macros.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Tim Deegan and Andrew Warfield November 2004.
> + */
> +
> +#ifndef __XEN_PUBLIC_IO_RING_H__
> +#define __XEN_PUBLIC_IO_RING_H__
> +
> +#include "../xen-compat.h"
> +
> +#if __XEN_INTERFACE_VERSION__ < 0x00030208
> +#define xen_mb()  mb()
> +#define xen_rmb() rmb()
> +#define xen_wmb() wmb()
> +#endif
> +
> +typedef UINT32 RING_IDX;
> +
> +/* Round a 32-bit unsigned constant down to the nearest power of two. */
> +#define __RD2(_x)  (((_x) & 0x00000002) ? 0x2                  : ((_x) & 0x1))
> +#define __RD4(_x)  (((_x) & 0x0000000c) ? __RD2((_x)>>2)<<2    : __RD2(_x))
> +#define __RD8(_x)  (((_x) & 0x000000f0) ? __RD4((_x)>>4)<<4    : __RD4(_x))
> +#define __RD16(_x) (((_x) & 0x0000ff00) ? __RD8((_x)>>8)<<8    : __RD8(_x))
> +#define __RD32(_x) (((_x) & 0xffff0000) ? __RD16((_x)>>16)<<16 : __RD16(_x))
> +
> +/*
> + * Calculate size of a shared ring, given the total available space for the
> + * ring and indexes (_sz), and the name tag of the request/response structure.
> + * A ring contains as many entries as will fit, rounded down to the nearest 
> + * power of two (so we can mask with (size-1) to loop around).
> + */
> +#define __CONST_RING_SIZE(_s, _sz) \
> +    (__RD32(((_sz) - offsetof(struct _s##_sring, ring)) / \
> +           sizeof(((struct _s##_sring *)0)->ring[0])))
> +/*
> + * The same for passing in an actual pointer instead of a name tag.
> + */
> +#define __RING_SIZE(_s, _sz) \
> +    (__RD32(((_sz) - (INTN)(_s)->ring + (INTN)(_s)) / sizeof((_s)->ring[0])))
> +
> +/*
> + * Macros to make the correct C datatypes for a new kind of ring.
> + * 
> + * To make a new ring datatype, you need to have two message structures,
> + * let's say request_t, and response_t already defined.
> + *
> + * In a header where you want the ring datatype declared, you then do:
> + *
> + *     DEFINE_RING_TYPES(mytag, request_t, response_t);
> + *
> + * These expand out to give you a set of types, as you can see below.
> + * The most important of these are:
> + * 
> + *     mytag_sring_t      - The shared ring.
> + *     mytag_front_ring_t - The 'front' half of the ring.
> + *     mytag_back_ring_t  - The 'back' half of the ring.
> + *
> + * To initialize a ring in your code you need to know the location and size
> + * of the shared memory area (PAGE_SIZE, for instance). To initialise
> + * the front half:
> + *
> + *     mytag_front_ring_t front_ring;
> + *     SHARED_RING_INIT((mytag_sring_t *)shared_page);
> + *     FRONT_RING_INIT(&front_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
> + *
> + * Initializing the back follows similarly (note that only the front
> + * initializes the shared ring):
> + *
> + *     mytag_back_ring_t back_ring;
> + *     BACK_RING_INIT(&back_ring, (mytag_sring_t *)shared_page, PAGE_SIZE);
> + */
> +
> +#define DEFINE_RING_TYPES(__name, __req_t, __rsp_t)                     \
> +                                                                        \
> +/* Shared ring entry */                                                 \
> +union __name##_sring_entry {                                            \
> +    __req_t req;                                                        \
> +    __rsp_t rsp;                                                        \
> +};                                                                      \
> +                                                                        \
> +/* Shared ring page */                                                  \
> +struct __name##_sring {                                                 \
> +    RING_IDX req_prod, req_event;                                       \
> +    RING_IDX rsp_prod, rsp_event;                                       \
> +    union {                                                             \
> +        struct {                                                        \
> +            UINT8 smartpoll_active;                                   \
> +        } netif;                                                        \
> +        struct {                                                        \
> +            UINT8 msg;                                                \
> +        } tapif_user;                                                   \
> +        UINT8 pvt_pad[4];                                             \
> +    } private;                                                          \
> +    UINT8 __pad[44];                                                  \
> +    union __name##_sring_entry ring[1]; /* variable-length */           \
> +};                                                                      \
> +                                                                        \
> +/* "Front" end's private variables */                                   \
> +struct __name##_front_ring {                                            \
> +    RING_IDX req_prod_pvt;                                              \
> +    RING_IDX rsp_cons;                                                  \
> +    UINT32 nr_ents;                                               \
> +    struct __name##_sring *sring;                                       \
> +};                                                                      \
> +                                                                        \
> +/* "Back" end's private variables */                                    \
> +struct __name##_back_ring {                                             \
> +    RING_IDX rsp_prod_pvt;                                              \
> +    RING_IDX req_cons;                                                  \
> +    UINT32 nr_ents;                                               \
> +    struct __name##_sring *sring;                                       \
> +};                                                                      \
> +                                                                        \
> +/* Syntactic sugar */                                                   \
> +typedef struct __name##_sring __name##_sring_t;                         \
> +typedef struct __name##_front_ring __name##_front_ring_t;               \
> +typedef struct __name##_back_ring __name##_back_ring_t
> +
> +/*
> + * Macros for manipulating rings.
> + * 
> + * FRONT_RING_whatever works on the "front end" of a ring: here 
> + * requests are pushed on to the ring and responses taken off it.
> + * 
> + * BACK_RING_whatever works on the "back end" of a ring: here 
> + * requests are taken off the ring and responses put on.
> + * 
> + * N.B. these macros do NO INTERLOCKS OR FLOW CONTROL. 
> + * This is OK in 1-for-1 request-response situations where the 
> + * requestor (front end) never has more than RING_SIZE()-1
> + * outstanding requests.
> + */
> +
> +/* Initialising empty rings */
> +#define SHARED_RING_INIT(_s) do {                                       \
> +    (_s)->req_prod  = (_s)->rsp_prod  = 0;                              \
> +    (_s)->req_event = (_s)->rsp_event = 1;                              \
> +    (VOID)ZeroMem((_s)->private.pvt_pad, sizeof((_s)->private.pvt_pad)); \
> +    (VOID)ZeroMem((_s)->__pad, sizeof((_s)->__pad));                  \
> +} while(0)
> +
> +#define FRONT_RING_INIT(_r, _s, __size) do {                            \
> +    (_r)->req_prod_pvt = 0;                                             \
> +    (_r)->rsp_cons = 0;                                                 \
> +    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
> +    (_r)->sring = (_s);                                                 \
> +} while (0)
> +
> +#define BACK_RING_INIT(_r, _s, __size) do {                             \
> +    (_r)->rsp_prod_pvt = 0;                                             \
> +    (_r)->req_cons = 0;                                                 \
> +    (_r)->nr_ents = __RING_SIZE(_s, __size);                            \
> +    (_r)->sring = (_s);                                                 \
> +} while (0)
> +
> +/* How big is this ring? */
> +#define RING_SIZE(_r)                                                   \
> +    ((_r)->nr_ents)
> +
> +/* Number of free requests (for use on front side only). */
> +#define RING_FREE_REQUESTS(_r)                                          \
> +    (RING_SIZE(_r) - ((_r)->req_prod_pvt - (_r)->rsp_cons))
> +
> +/* Test if there is an empty slot available on the front ring.
> + * (This is only meaningful from the front. )
> + */
> +#define RING_FULL(_r)                                                   \
> +    (RING_FREE_REQUESTS(_r) == 0)
> +
> +/* Test if there are outstanding messages to be processed on a ring. */
> +#define RING_HAS_UNCONSUMED_RESPONSES(_r)                               \
> +    ((_r)->sring->rsp_prod - (_r)->rsp_cons)
> +
> +#ifdef __GNUC__
> +#define RING_HAS_UNCONSUMED_REQUESTS(_r) ({                             \
> +    UINT32 req = (_r)->sring->req_prod - (_r)->req_cons;          \
> +    UINT32 rsp = RING_SIZE(_r) -                                  \
> +        ((_r)->req_cons - (_r)->rsp_prod_pvt);                          \
> +    req < rsp ? req : rsp;                                              \
> +})
> +#else
> +/* Same as above, but without the nice GCC ({ ... }) syntax. */
> +#define RING_HAS_UNCONSUMED_REQUESTS(_r)                                \
> +    ((((_r)->sring->req_prod - (_r)->req_cons) <                        \
> +      (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt))) ?        \
> +     ((_r)->sring->req_prod - (_r)->req_cons) :                         \
> +     (RING_SIZE(_r) - ((_r)->req_cons - (_r)->rsp_prod_pvt)))
> +#endif
> +
> +/* Direct access to individual ring elements, by index. */
> +#define RING_GET_REQUEST(_r, _idx)                                      \
> +    (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
> +
> +#define RING_GET_RESPONSE(_r, _idx)                                     \
> +    (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
> +
> +/* Loop termination condition: Would the specified index overflow the ring? */
> +#define RING_REQUEST_CONS_OVERFLOW(_r, _cons)                           \
> +    (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r))
> +
> +/* Ill-behaved frontend determination: Can there be this many requests? */
> +#define RING_REQUEST_PROD_OVERFLOW(_r, _prod)                           \
> +    (((_prod) - (_r)->rsp_prod_pvt) > RING_SIZE(_r))
> +
> +#define RING_PUSH_REQUESTS(_r) do {                                     \
> +    xen_wmb(); /* back sees requests /before/ updated producer index */ \
> +    (_r)->sring->req_prod = (_r)->req_prod_pvt;                         \
> +} while (0)
> +
> +#define RING_PUSH_RESPONSES(_r) do {                                    \
> +    xen_wmb(); /* front sees resps /before/ updated producer index */   \
> +    (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt;                         \
> +} while (0)
> +
> +/*
> + * Notification hold-off (req_event and rsp_event):
> + * 
> + * When queueing requests or responses on a shared ring, it may not always be
> + * necessary to notify the remote end. For example, if requests are in flight
> + * in a backend, the front may be able to queue further requests without
> + * notifying the back (if the back checks for new requests when it queues
> + * responses).
> + * 
> + * When enqueuing requests or responses:
> + * 
> + *  Use RING_PUSH_{REQUESTS,RESPONSES}_AND_CHECK_NOTIFY(). The second argument
> + *  is a boolean return value. True indicates that the receiver requires an
> + *  asynchronous notification.
> + * 
> + * After dequeuing requests or responses (before sleeping the connection):
> + * 
> + *  Use RING_FINAL_CHECK_FOR_REQUESTS() or RING_FINAL_CHECK_FOR_RESPONSES().
> + *  The second argument is a boolean return value. True indicates that there
> + *  are pending messages on the ring (i.e., the connection should not be put
> + *  to sleep).
> + * 
> + *  These macros will set the req_event/rsp_event field to trigger a
> + *  notification on the very next message that is enqueued. If you want to
> + *  create batches of work (i.e., only receive a notification after several
> + *  messages have been enqueued) then you will need to create a customised
> + *  version of the FINAL_CHECK macro in your own code, which sets the event
> + *  field appropriately.
> + */
> +
> +#define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do {           \
> +    RING_IDX __old = (_r)->sring->req_prod;                             \
> +    RING_IDX __new = (_r)->req_prod_pvt;                                \
> +    xen_wmb(); /* back sees requests /before/ updated producer index */ \
> +    (_r)->sring->req_prod = __new;                                      \
> +    xen_mb(); /* back sees new requests /before/ we check req_event */  \
> +    (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) <           \
> +                 (RING_IDX)(__new - __old));                            \
> +} while (0)
> +
> +#define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do {          \
> +    RING_IDX __old = (_r)->sring->rsp_prod;                             \
> +    RING_IDX __new = (_r)->rsp_prod_pvt;                                \
> +    xen_wmb(); /* front sees resps /before/ updated producer index */   \
> +    (_r)->sring->rsp_prod = __new;                                      \
> +    xen_mb(); /* front sees new resps /before/ we check rsp_event */    \
> +    (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) <           \
> +                 (RING_IDX)(__new - __old));                            \
> +} while (0)
> +
> +#define RING_FINAL_CHECK_FOR_REQUESTS(_r, _work_to_do) do {             \
> +    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
> +    if (_work_to_do) break;                                             \
> +    (_r)->sring->req_event = (_r)->req_cons + 1;                        \
> +    xen_mb();                                                           \
> +    (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r);                   \
> +} while (0)
> +
> +#define RING_FINAL_CHECK_FOR_RESPONSES(_r, _work_to_do) do {            \
> +    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
> +    if (_work_to_do) break;                                             \
> +    (_r)->sring->rsp_event = (_r)->rsp_cons + 1;                        \
> +    xen_mb();                                                           \
> +    (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r);                  \
> +} while (0)
> +
> +#endif /* __XEN_PUBLIC_IO_RING_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h b/OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h
> new file mode 100644
> index 0000000..927f9db
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/io/xenbus.h
> @@ -0,0 +1,80 @@
> +/*****************************************************************************
> + * xenbus.h
> + *
> + * Xenbus protocol details.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (C) 2005 XenSource Ltd.
> + */
> +
> +#ifndef _XEN_PUBLIC_IO_XENBUS_H
> +#define _XEN_PUBLIC_IO_XENBUS_H
> +
> +/*
> + * The state of either end of the Xenbus, i.e. the current communication
> + * status of initialisation across the bus.  States here imply nothing about
> + * the state of the connection between the driver and the kernel's device
> + * layers.
> + */
> +enum xenbus_state {
> +    XenbusStateUnknown       = 0,
> +
> +    XenbusStateInitialising  = 1,
> +
> +    /*
> +     * InitWait: Finished early initialisation but waiting for information
> +     * from the peer or hotplug scripts.
> +     */
> +    XenbusStateInitWait      = 2,
> +
> +    /*
> +     * Initialised: Waiting for a connection from the peer.
> +     */
> +    XenbusStateInitialised   = 3,
> +
> +    XenbusStateConnected     = 4,
> +
> +    /*
> +     * Closing: The device is being closed due to an error or an unplug event.
> +     */
> +    XenbusStateClosing       = 5,
> +
> +    XenbusStateClosed        = 6,
> +
> +    /*
> +     * Reconfiguring: The device is being reconfigured.
> +     */
> +    XenbusStateReconfiguring = 7,
> +
> +    XenbusStateReconfigured  = 8
> +};
> +typedef enum xenbus_state XenbusState;
> +
> +#endif /* _XEN_PUBLIC_IO_XENBUS_H */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/memory.h b/OvmfPkg/Include/IndustryStandard/Xen/memory.h
> new file mode 100644
> index 0000000..00156a4
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/memory.h
> @@ -0,0 +1,94 @@
> +/******************************************************************************
> + * memory.h
> + * 
> + * Memory reservation and information.
> + * 
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (c) 2005, Keir Fraser <keir@xensource.com>
> + */
> +
> +#ifndef __XEN_PUBLIC_MEMORY_H__
> +#define __XEN_PUBLIC_MEMORY_H__
> +
> +#include "xen.h"
> +
> +/* Source mapping space. */
> +/* ` enum phys_map_space { */
> +#define XENMAPSPACE_shared_info  0 /* shared info page */
> +#define XENMAPSPACE_grant_table  1 /* grant table page */
> +#define XENMAPSPACE_gmfn         2 /* GMFN */
> +#define XENMAPSPACE_gmfn_range   3 /* GMFN range, XENMEM_add_to_physmap only. */
> +#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
> +                                    * XENMEM_add_to_physmap_batch only. */
> +/* ` } */
> +
> +/*
> + * Sets the GPFN at which a particular page appears in the specified guest's
> + * pseudophysical address space.
> + * arg == addr of xen_add_to_physmap_t.
> + */
> +#define XENMEM_add_to_physmap      7
> +struct xen_add_to_physmap {
> +    /* Which domain to change the mapping for. */
> +    domid_t domid;
> +
> +    /* Number of pages to go through for gmfn_range */
> +    UINT16    size;
> +
> +    UINT32 space; /* => enum phys_map_space */
> +
> +#define XENMAPIDX_grant_table_status 0x80000000
> +
> +    /* Index into space being mapped. */
> +    xen_ulong_t idx;
> +
> +    /* GPFN in domid where the source mapping page should appear. */
> +    xen_pfn_t     gpfn;
> +};
> +typedef struct xen_add_to_physmap xen_add_to_physmap_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_add_to_physmap_t);
> +
> +/*
> + * Unmaps the page appearing at a particular GPFN from the specified guest's
> + * pseudophysical address space.
> + * arg == addr of xen_remove_from_physmap_t.
> + */
> +#define XENMEM_remove_from_physmap      15
> +struct xen_remove_from_physmap {
> +    /* Which domain to change the mapping for. */
> +    domid_t domid;
> +
> +    /* GPFN of the current mapping of the page. */
> +    xen_pfn_t     gpfn;
> +};
> +typedef struct xen_remove_from_physmap xen_remove_from_physmap_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_remove_from_physmap_t);
> +
> +#endif /* __XEN_PUBLIC_MEMORY_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h b/OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h
> new file mode 100644
> index 0000000..3eb80a0
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/xen-compat.h
> @@ -0,0 +1,44 @@
> +/******************************************************************************
> + * xen-compat.h
> + * 
> + * Guest OS interface to Xen.  Compatibility layer.
> + * 
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (c) 2006, Christian Limpach
> + */
> +
> +#ifndef __XEN_PUBLIC_XEN_COMPAT_H__
> +#define __XEN_PUBLIC_XEN_COMPAT_H__
> +
> +#define __XEN_LATEST_INTERFACE_VERSION__ 0x00040400
> +
> +#if defined(__XEN__) || defined(__XEN_TOOLS__)
> +/* Xen is built with matching headers and implements the latest interface. */
> +#define __XEN_INTERFACE_VERSION__ __XEN_LATEST_INTERFACE_VERSION__
> +#elif !defined(__XEN_INTERFACE_VERSION__)
> +/* Guests which do not specify a version get the legacy interface. */
> +#define __XEN_INTERFACE_VERSION__ 0x00000000
> +#endif
> +
> +#if __XEN_INTERFACE_VERSION__ > __XEN_LATEST_INTERFACE_VERSION__
> +#error "These header files do not support the requested interface version."
> +#endif
> +
> +#endif /* __XEN_PUBLIC_XEN_COMPAT_H__ */
> diff --git a/OvmfPkg/Include/IndustryStandard/Xen/xen.h b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
> new file mode 100644
> index 0000000..b93bd47
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Xen/xen.h
> @@ -0,0 +1,341 @@
> +/******************************************************************************
> + * xen.h
> + * 
> + * Guest OS interface to Xen.
> + * 
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to
> + * deal in the Software without restriction, including without limitation the
> + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
> + * sell copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + *
> + * Copyright (c) 2004, K A Fraser
> + */
> +
> +#ifndef __XEN_PUBLIC_XEN_H__
> +#define __XEN_PUBLIC_XEN_H__
> +
> +#include "xen-compat.h"
> +
> +#if defined(__i386__) || defined(__x86_64__)
> +#include "arch-x86/xen.h"
> +#elif defined(__arm__) || defined (__aarch64__)
> +#include "arch-arm.h"
> +#else
> +#error "Unsupported architecture"
> +#endif
> +
> +#ifndef __ASSEMBLY__
> +/* Guest handles for primitive C types. */
> +DEFINE_XEN_GUEST_HANDLE(CHAR8);
> +/* __DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); */
> +DEFINE_XEN_GUEST_HANDLE(INT32);
> +__DEFINE_XEN_GUEST_HANDLE(uint,  UINT32);
> +#if __XEN_INTERFACE_VERSION__ < 0x00040300
> +DEFINE_XEN_GUEST_HANDLE(INTN);
> +__DEFINE_XEN_GUEST_HANDLE(ulong, UINTN);
> +#endif
> +DEFINE_XEN_GUEST_HANDLE(VOID);
> +
> +DEFINE_XEN_GUEST_HANDLE(UINT64);
> +DEFINE_XEN_GUEST_HANDLE(xen_pfn_t);
> +DEFINE_XEN_GUEST_HANDLE(xen_ulong_t);
> +#endif
> +
> +/*
> + * HYPERCALLS
> + */
> +
> +/* `incontents 100 hcalls List of hypercalls
> + * ` enum hypercall_num { // __HYPERVISOR_* => HYPERVISOR_*()
> + */
> +
> +#define __HYPERVISOR_set_trap_table        0
> +#define __HYPERVISOR_mmu_update            1
> +#define __HYPERVISOR_set_gdt               2
> +#define __HYPERVISOR_stack_switch          3
> +#define __HYPERVISOR_set_callbacks         4
> +#define __HYPERVISOR_fpu_taskswitch        5
> +#define __HYPERVISOR_sched_op_compat       6 /* compat since 0x00030101 */
> +#define __HYPERVISOR_platform_op           7
> +#define __HYPERVISOR_set_debugreg          8
> +#define __HYPERVISOR_get_debugreg          9
> +#define __HYPERVISOR_update_descriptor    10
> +#define __HYPERVISOR_memory_op            12
> +#define __HYPERVISOR_multicall            13
> +#define __HYPERVISOR_update_va_mapping    14
> +#define __HYPERVISOR_set_timer_op         15
> +#define __HYPERVISOR_event_channel_op_compat 16 /* compat since 0x00030202 */
> +#define __HYPERVISOR_xen_version          17
> +#define __HYPERVISOR_console_io           18
> +#define __HYPERVISOR_physdev_op_compat    19 /* compat since 0x00030202 */
> +#define __HYPERVISOR_grant_table_op       20
> +#define __HYPERVISOR_vm_assist            21
> +#define __HYPERVISOR_update_va_mapping_otherdomain 22
> +#define __HYPERVISOR_iret                 23 /* x86 only */
> +#define __HYPERVISOR_vcpu_op              24
> +#define __HYPERVISOR_set_segment_base     25 /* x86/64 only */
> +#define __HYPERVISOR_mmuext_op            26
> +#define __HYPERVISOR_xsm_op               27
> +#define __HYPERVISOR_nmi_op               28
> +#define __HYPERVISOR_sched_op             29
> +#define __HYPERVISOR_callback_op          30
> +#define __HYPERVISOR_xenoprof_op          31
> +#define __HYPERVISOR_event_channel_op     32
> +#define __HYPERVISOR_physdev_op           33
> +#define __HYPERVISOR_hvm_op               34
> +#define __HYPERVISOR_sysctl               35
> +#define __HYPERVISOR_domctl               36
> +#define __HYPERVISOR_kexec_op             37
> +#define __HYPERVISOR_tmem_op              38
> +#define __HYPERVISOR_xc_reserved_op       39 /* reserved for XenClient */
> +
> +/* Architecture-specific hypercall definitions. */
> +#define __HYPERVISOR_arch_0               48
> +#define __HYPERVISOR_arch_1               49
> +#define __HYPERVISOR_arch_2               50
> +#define __HYPERVISOR_arch_3               51
> +#define __HYPERVISOR_arch_4               52
> +#define __HYPERVISOR_arch_5               53
> +#define __HYPERVISOR_arch_6               54
> +#define __HYPERVISOR_arch_7               55
> +
> +/* ` } */
> +
> +/*
> + * HYPERCALL COMPATIBILITY.
> + */
> +
> +/* New sched_op hypercall introduced in 0x00030101. */
> +#if __XEN_INTERFACE_VERSION__ < 0x00030101
> +#undef __HYPERVISOR_sched_op
> +#define __HYPERVISOR_sched_op __HYPERVISOR_sched_op_compat
> +#endif
> +
> +/* New event-channel and physdev hypercalls introduced in 0x00030202. */
> +#if __XEN_INTERFACE_VERSION__ < 0x00030202
> +#undef __HYPERVISOR_event_channel_op
> +#define __HYPERVISOR_event_channel_op __HYPERVISOR_event_channel_op_compat
> +#undef __HYPERVISOR_physdev_op
> +#define __HYPERVISOR_physdev_op __HYPERVISOR_physdev_op_compat
> +#endif
> +
> +/* New platform_op hypercall introduced in 0x00030204. */
> +#if __XEN_INTERFACE_VERSION__ < 0x00030204
> +#define __HYPERVISOR_dom0_op __HYPERVISOR_platform_op
> +#endif
> +
> +#ifndef __ASSEMBLY__
> +
> +typedef UINT16 domid_t;
> +
> +/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */
> +#define DOMID_FIRST_RESERVED (0x7FF0U)
> +
> +/* DOMID_SELF is used in certain contexts to refer to oneself. */
> +#define DOMID_SELF (0x7FF0U)
> +
> +/*
> + * DOMID_IO is used to restrict page-table updates to mapping I/O memory.
> + * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO
> + * is useful to ensure that no mappings to the OS's own heap are accidentally
> + * installed. (e.g., in Linux this could cause havoc as reference counts
> + * aren't adjusted on the I/O-mapping code path).
> + * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can
> + * be specified by any calling domain.
> + */
> +#define DOMID_IO   (0x7FF1U)
> +
> +/*
> + * DOMID_XEN is used to allow privileged domains to map restricted parts of
> + * Xen's heap space (e.g., the machine_to_phys table).
> + * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if
> + * the caller is privileged.
> + */
> +#define DOMID_XEN  (0x7FF2U)
> +
> +/*
> + * DOMID_COW is used as the owner of sharable pages */
> +#define DOMID_COW  (0x7FF3U)
> +
> +/* DOMID_INVALID is used to identify pages with unknown owner. */
> +#define DOMID_INVALID (0x7FF4U)
> +
> +/* Idle domain. */
> +#define DOMID_IDLE (0x7FFFU)
> +
> +#if __XEN_INTERFACE_VERSION__ < 0x00040400
> +/*
> + * Event channel endpoints per domain (when using the 2-level ABI):
> + *  1024 if a INTN is 32 bits; 4096 if a INTN is 64 bits.
> + */
> +#define NR_EVENT_CHANNELS EVTCHN_2L_NR_CHANNELS
> +#endif
> +
> +struct vcpu_time_info {
> +    /*
> +     * Updates to the following values are preceded and followed by an
> +     * increment of 'version'. The guest can therefore detect updates by
> +     * looking for changes to 'version'. If the least-significant bit of
> +     * the version number is set then an update is in progress and the guest
> +     * must wait to read a consistent set of values.
> +     * The correct way to interact with the version number is similar to
> +     * Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
> +     */
> +    UINT32 version;
> +    UINT32 pad0;
> +    UINT64 tsc_timestamp;   /* TSC at last update of time vals.  */
> +    UINT64 system_time;     /* Time, in nanosecs, since boot.    */
> +    /*
> +     * Current system time:
> +     *   system_time +
> +     *   ((((tsc - tsc_timestamp) << tsc_shift) * tsc_to_system_mul) >> 32)
> +     * CPU frequency (Hz):
> +     *   ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
> +     */
> +    UINT32 tsc_to_system_mul;
> +    INT8   tsc_shift;
> +    INT8   pad1[3];
> +}; /* 32 bytes */
> +typedef struct vcpu_time_info vcpu_time_info_t;
> +
> +struct vcpu_info {
> +    /*
> +     * 'evtchn_upcall_pending' is written non-zero by Xen to indicate
> +     * a pending notification for a particular VCPU. It is then cleared 
> +     * by the guest OS /before/ checking for pending work, thus avoiding
> +     * a set-and-check race. Note that the mask is only accessed by Xen
> +     * on the CPU that is currently hosting the VCPU. This means that the
> +     * pending and mask flags can be updated by the guest without special
> +     * synchronisation (i.e., no need for the x86 LOCK prefix).
> +     * This may seem suboptimal because if the pending flag is set by
> +     * a different CPU then an IPI may be scheduled even when the mask
> +     * is set. However, note:
> +     *  1. The task of 'interrupt holdoff' is covered by the per-event-
> +     *     channel mask bits. A 'noisy' event that is continually being
> +     *     triggered can be masked at source at this very precise
> +     *     granularity.
> +     *  2. The main purpose of the per-VCPU mask is therefore to restrict
> +     *     reentrant execution: whether for concurrency control, or to
> +     *     prevent unbounded stack usage. Whatever the purpose, we expect
> +     *     that the mask will be asserted only for short periods at a time,
> +     *     and so the likelihood of a 'spurious' IPI is suitably small.
> +     * The mask is read before making an event upcall to the guest: a
> +     * non-zero mask therefore guarantees that the VCPU will not receive
> +     * an upcall activation. The mask is cleared when the VCPU requests
> +     * to block: this avoids wakeup-waiting races.
> +     */
> +    UINT8 evtchn_upcall_pending;
> +#ifdef XEN_HAVE_PV_UPCALL_MASK
> +    UINT8 evtchn_upcall_mask;
> +#else /* XEN_HAVE_PV_UPCALL_MASK */
> +    UINT8 pad0;
> +#endif /* XEN_HAVE_PV_UPCALL_MASK */
> +    xen_ulong_t evtchn_pending_sel;
> +    struct arch_vcpu_info arch;
> +    struct vcpu_time_info time;
> +}; /* 64 bytes (x86) */
> +#ifndef __XEN__
> +typedef struct vcpu_info vcpu_info_t;
> +#endif
> +
> +/*
> + * `incontents 200 startofday_shared Start-of-day shared data structure
> + * Xen/kernel shared data -- pointer provided in start_info.
> + *
> + * This structure is defined to be both smaller than a page, and the
> + * only data on the shared page, but may vary in actual size even within
> + * compatible Xen versions; guests should not rely on the size
> + * of this structure remaining constant.
> + */
> +struct shared_info {
> +    struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
> +
> +    /*
> +     * A domain can create "event channels" on which it can send and receive
> +     * asynchronous event notifications. There are three classes of event that
> +     * are delivered by this mechanism:
> +     *  1. Bi-directional inter- and intra-domain connections. Domains must
> +     *     arrange out-of-band to set up a connection (usually by allocating
> +     *     an unbound 'listener' port and avertising that via a storage service
> +     *     such as xenstore).
> +     *  2. Physical interrupts. A domain with suitable hardware-access
> +     *     privileges can bind an event-channel port to a physical interrupt
> +     *     source.
> +     *  3. Virtual interrupts ('events'). A domain can bind an event-channel
> +     *     port to a virtual interrupt source, such as the virtual-timer
> +     *     device or the emergency console.
> +     * 
> +     * Event channels are addressed by a "port index". Each channel is
> +     * associated with two bits of information:
> +     *  1. PENDING -- notifies the domain that there is a pending notification
> +     *     to be processed. This bit is cleared by the guest.
> +     *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
> +     *     will cause an asynchronous upcall to be scheduled. This bit is only
> +     *     updated by the guest. It is read-only within Xen. If a channel
> +     *     becomes pending while the channel is masked then the 'edge' is lost
> +     *     (i.e., when the channel is unmasked, the guest must manually handle
> +     *     pending notifications as no upcall will be scheduled by Xen).
> +     * 
> +     * To expedite scanning of pending notifications, any 0->1 pending
> +     * transition on an unmasked channel causes a corresponding bit in a
> +     * per-vcpu selector word to be set. Each bit in the selector covers a
> +     * 'C INTN' in the PENDING bitfield array.
> +     */
> +    xen_ulong_t evtchn_pending[sizeof(xen_ulong_t) * 8];
> +    xen_ulong_t evtchn_mask[sizeof(xen_ulong_t) * 8];
> +
> +    /*
> +     * Wallclock time: updated only by control software. Guests should base
> +     * their gettimeofday() syscall on this wallclock-base value.
> +     */
> +    UINT32 wc_version;      /* Version counter: see vcpu_time_info_t. */
> +    UINT32 wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
> +    UINT32 wc_nsec;         /* Nsecs 00:00:00 UTC, Jan 1, 1970.  */
> +
> +    struct arch_shared_info arch;
> +
> +};
> +#ifndef __XEN__
> +typedef struct shared_info shared_info_t;
> +#endif
> +
> +/* Turn a plain number into a C UINTN constant. */
> +#define __mk_unsigned_long(x) x ## UL
> +#define mk_unsigned_long(x) __mk_unsigned_long(x)
> +
> +__DEFINE_XEN_GUEST_HANDLE(uint8,  UINT8);
> +__DEFINE_XEN_GUEST_HANDLE(uint16, UINT16);
> +__DEFINE_XEN_GUEST_HANDLE(uint32, UINT32);
> +__DEFINE_XEN_GUEST_HANDLE(uint64, UINT64);
> +
> +#else /* __ASSEMBLY__ */
> +
> +/* In assembly code we cannot use C numeric constant suffixes. */
> +#define mk_unsigned_long(x) x
> +
> +#endif /* !__ASSEMBLY__ */
> +
> +#endif /* __XEN_PUBLIC_XEN_H__ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> -- 
> Anthony PERARD
> 
> 
> ------------------------------------------------------------------------------
> Comprehensive Server Monitoring with Site24x7.
> Monitor 10 servers for $9/Month.
> Get alerted through email, SMS, voice calls or mobile push notifications.
> Take corrective actions from your mobile device.
> http://p.sf.net/sfu/Zoho
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/edk2-devel

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

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

* Re: [edk2] [PATCH v3 08/19] OvmfPkg/XenBusDxe: Add InterlockedCompareExchange16.
       [not found] ` <1413565442-29149-9-git-send-email-anthony.perard@citrix.com>
@ 2014-10-20  0:00   ` Jordan Justen
       [not found]   ` <20141020000013.22698.55324@jljusten-ivy>
  1 sibling, 0 replies; 29+ messages in thread
From: Jordan Justen @ 2014-10-20  0:00 UTC (permalink / raw)
  To: edk2-devel, Anthony PERARD; +Cc: Xen Devel

On 2014-10-17 10:03:51, Anthony PERARD wrote:
> This patch is inspired by InterlockedCompareExchange32 from the
> BaseSynchronizationLib.

Why not attempt to add it to BaseSynchronizationLib?

-Jordan

> The function will be used in the "OvmfPkg/XenBusDxe: Add Grant Table
> functions" patch.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> 
> ---
> Change in V3:
> - Implement both .S and .asm, to get rid of GCC specific asm.
> - Implement 32bit part of the assembly
> 
> Change in V2:
> - Add intel compilation code
>   MSFT code is not compied over because I don't know how it works.
> ---
>  .../XenBusDxe/Ia32/InterlockedCompareExchange16.S  | 15 ++++++++
>  .../Ia32/InterlockedCompareExchange16.asm          | 45 ++++++++++++++++++++++
>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c   | 33 ++++++++++++++++
>  OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h   | 38 ++++++++++++++++++
>  .../XenBusDxe/X64/InterlockedCompareExchange16.S   | 13 +++++++
>  .../XenBusDxe/X64/InterlockedCompareExchange16.asm | 41 ++++++++++++++++++++
>  OvmfPkg/XenBusDxe/XenBusDxe.inf                    |  6 +++
>  7 files changed, 191 insertions(+)
>  create mode 100644 OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S
>  create mode 100644 OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm
>  create mode 100644 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
>  create mode 100644 OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
>  create mode 100644 OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S
>  create mode 100644 OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm
> 
> diff --git a/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S
> new file mode 100644
> index 0000000..b4adb66
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.S
> @@ -0,0 +1,15 @@
> +# UINT16
> +# EFIAPI
> +# InternalSyncCompareExchange16 (
> +#   IN      volatile UINT16           *Value,
> +#   IN      UINT16                    CompareValue,
> +#   IN      UINT16                    ExchangeValue
> +#   );
> +ASM_GLOBAL ASM_PFX(InternalSyncCompareExchange16)
> +ASM_PFX(InternalSyncCompareExchange16):
> +  mov 4(%esp), %ecx
> +  mov 8(%esp), %eax
> +  mov 12(%esp), %edx
> +  lock
> +  cmpxchgw %dx, (%ecx)
> +  ret
> diff --git a/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm
> new file mode 100644
> index 0000000..adcfbd0
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/Ia32/InterlockedCompareExchange16.asm
> @@ -0,0 +1,45 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; This program and the accompanying materials
> +; are licensed and made available under the terms and conditions of the BSD License
> +; which accompanies this distribution.  The full text of the license may be found at
> +; http://opensource.org/licenses/bsd-license.php.
> +;
> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .486
> +    .model  flat,C
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT32
> +; EFIAPI
> +; InternalSyncCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     ecx, [esp + 4]
> +    mov     eax, [esp + 8]
> +    mov     edx, [esp + 12]
> +    lock    cmpxchg [ecx], dx
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
> new file mode 100644
> index 0000000..89d96d1
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.c
> @@ -0,0 +1,33 @@
> +#include <Library/DebugLib.h>
> +#include "InterlockedCompareExchange16.h"
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  )
> +{
> +  ASSERT (Value != NULL);
> +  return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
> +}
> diff --git a/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
> new file mode 100644
> index 0000000..e863dbd
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/InterlockedCompareExchange16.h
> @@ -0,0 +1,38 @@
> +/**
> +  Assembly implementation of InterlockedCompareExchange16.
> +
> +  Look at the documentation of InterlockedCompareExchange16.
> +**/
> +UINT16
> +EFIAPI
> +InternalSyncCompareExchange16 (
> +  IN      volatile UINT16           *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> +
> +/**
> +  Performs an atomic compare exchange operation on a 16-bit unsigned integer.
> +
> +  Performs an atomic compare exchange operation on the 16-bit unsigned integer
> +  specified by Value.  If Value is equal to CompareValue, then Value is set to
> +  ExchangeValue and CompareValue is returned.  If Value is not equal to CompareValue,
> +  then Value is returned.  The compare exchange operation must be performed using
> +  MP safe mechanisms.
> +
> +  If Value is NULL, then ASSERT().
> +
> +  @param  Value         A pointer to the 16-bit value for the compare exchange
> +                        operation.
> +  @param  CompareValue  16-bit value used in compare operation.
> +  @param  ExchangeValue 16-bit value used in exchange operation.
> +
> +  @return The original *Value before exchange.
> +**/
> +UINT16
> +EFIAPI
> +InterlockedCompareExchange16 (
> +  IN OUT  UINT16                    *Value,
> +  IN      UINT16                    CompareValue,
> +  IN      UINT16                    ExchangeValue
> +  );
> diff --git a/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S
> new file mode 100644
> index 0000000..c6336ca
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.S
> @@ -0,0 +1,13 @@
> +# UINT16
> +# EFIAPI
> +# InternalSyncCompareExchange16 (
> +#   IN      volatile UINT16           *Value,
> +#   IN      UINT16                    CompareValue,
> +#   IN      UINT16                    ExchangeValue
> +#   );
> +ASM_GLOBAL ASM_PFX(InternalSyncCompareExchange16)
> +ASM_PFX(InternalSyncCompareExchange16):
> +  mov %edx, %eax
> +  lock
> +  cmpxchgw %r8w, (%rcx)
> +  ret
> diff --git a/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm
> new file mode 100644
> index 0000000..b23e421
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/X64/InterlockedCompareExchange16.asm
> @@ -0,0 +1,41 @@
> +;------------------------------------------------------------------------------
> +;
> +; Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
> +; This program and the accompanying materials
> +; are licensed and made available under the terms and conditions of the BSD License
> +; which accompanies this distribution.  The full text of the license may be found at
> +; http://opensource.org/licenses/bsd-license.php.
> +;
> +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
> +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> +;
> +; Module Name:
> +;
> +;   InterlockedCompareExchange16.Asm
> +;
> +; Abstract:
> +;
> +;   InterlockedCompareExchange16 function
> +;
> +; Notes:
> +;
> +;------------------------------------------------------------------------------
> +
> +    .code
> +
> +;------------------------------------------------------------------------------
> +; UINT16
> +; EFIAPI
> +; InterlockedCompareExchange16 (
> +;   IN      UINT16                    *Value,
> +;   IN      UINT16                    CompareValue,
> +;   IN      UINT16                    ExchangeValue
> +;   );
> +;------------------------------------------------------------------------------
> +InternalSyncCompareExchange16   PROC
> +    mov     eax, edx
> +    lock    cmpxchg [rcx], r8w
> +    ret
> +InternalSyncCompareExchange16   ENDP
> +
> +    END
> diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> index e5bfff6..444118a 100644
> --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
> +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> @@ -33,14 +33,20 @@
>    ComponentName.h
>    XenHypercall.c
>    XenHypercall.h
> +  InterlockedCompareExchange16.c
> +  InterlockedCompareExchange16.h
>  
>  [Sources.IA32]
>    Ia32/hypercall.S
>    Ia32/hypercall.asm
> +  Ia32/InterlockedCompareExchange16.S
> +  Ia32/InterlockedCompareExchange16.asm
>  
>  [Sources.X64]
>    X64/hypercall.S
>    X64/hypercall.asm
> +  X64/InterlockedCompareExchange16.S
> +  X64/InterlockedCompareExchange16.asm
>  
>  [LibraryClasses]
>    UefiDriverEntryPoint
> -- 
> Anthony PERARD
> 
> 
> ------------------------------------------------------------------------------
> Comprehensive Server Monitoring with Site24x7.
> Monitor 10 servers for $9/Month.
> Get alerted through email, SMS, voice calls or mobile push notifications.
> Take corrective actions from your mobile device.
> http://p.sf.net/sfu/Zoho
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/edk2-devel

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

* Re: [edk2] [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce XenBus support itself.
       [not found] ` <1413565442-29149-16-git-send-email-anthony.perard@citrix.com>
@ 2014-10-20  0:20   ` Jordan Justen
       [not found]   ` <20141020002045.22698.90635@jljusten-ivy>
  1 sibling, 0 replies; 29+ messages in thread
From: Jordan Justen @ 2014-10-20  0:20 UTC (permalink / raw)
  To: edk2-devel, Anthony PERARD; +Cc: Xen Devel

On 2014-10-17 10:03:58, Anthony PERARD wrote:
> This is a bus-like on top of XenStore. It will look for advertised
> ParaVirtualized devices and initialize them by producing XenBus
> protocol.
> 
> Origin: FreeBSD 10.0
> 
> License: This patch adds XenBus.c which is under the MIT licence.
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> 
> ---
> Change in V3:
> - Insert to ChildList later, once populated.
> - Remove XENBUS_XENSTORE_NODE macro.
> - add comment to XenBusAddDevice and XenBusEnumerateBus about
>   concurrency calls.
> - Add a description to the introduced member to the protocol.
> 
> Change in V2:
> - comment, file header
> - Fix comment style
> - Error handling in the main init function
> - coding style
> - Fix error path in add device.
> ---
>  OvmfPkg/Include/Protocol/XenBus.h |  19 ++
>  OvmfPkg/XenBusDxe/XenBus.c        | 372 ++++++++++++++++++++++++++++++++++++++
>  OvmfPkg/XenBusDxe/XenBus.h        |  64 +++++++
>  OvmfPkg/XenBusDxe/XenBusDxe.c     |  66 +++++++
>  OvmfPkg/XenBusDxe/XenBusDxe.h     |  19 ++
>  OvmfPkg/XenBusDxe/XenBusDxe.inf   |   3 +
>  6 files changed, 543 insertions(+)
>  create mode 100644 OvmfPkg/XenBusDxe/XenBus.c
>  create mode 100644 OvmfPkg/XenBusDxe/XenBus.h

> diff --git a/OvmfPkg/XenBusDxe/XenBus.h b/OvmfPkg/XenBusDxe/XenBus.h
> new file mode 100644
> index 0000000..7ff25c3
> --- /dev/null
> +++ b/OvmfPkg/XenBusDxe/XenBus.h
> @@ -0,0 +1,64 @@
> +/** @file
> +  Core definitions and data structures shareable across OS platforms.
> +
> +  Copyright (c) 2010 Spectra Logic Corporation
> +  Copyright (C) 2008 Doug Rabson
> +  All rights reserved.
> +  Copyright (C) 2014, Citrix Ltd.
> +
> +  Redistribution and use in source and binary forms, with or without
> +  modification, are permitted provided that the following conditions
> +  are met:
> +  1. Redistributions of source code must retain the above copyright
> +     notice, this list of conditions, and the following disclaimer,
> +     without modification.
> +  2. Redistributions in binary form must reproduce at minimum a disclaimer
> +     substantially similar to the "NO WARRANTY" disclaimer below
> +     ("Disclaimer") and any redistribution must be conditioned upon
> +     including a substantially similar Disclaimer requirement for further
> +     binary redistribution.
> +
> +  NO WARRANTY
> +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
> +  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> +  HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> +  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> +  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> +  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> +  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> +  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +  POSSIBILITY OF SUCH DAMAGES.

What is this license?

The code below appears to have been written just for EDK II, so maybe
just use the standard EDK II license header?

-Jordan

> +
> +**/
> +#ifndef _XEN_XENBUS_XENBUSB_H
> +#define _XEN_XENBUS_XENBUSB_H
> +
> +#include "XenBusDxe.h"
> +
> +#define XENBUS_DEVICE_PATH_TYPE_VBD 0x1
> +struct _XENBUS_DEVICE_PATH {
> +  VENDOR_DEVICE_PATH  Vendor;
> +  UINT8               Type;
> +  UINT16              DeviceId;
> +};
> +
> +
> +/**
> +  Perform XenBus bus enumeration and install protocol for children.
> +
> +  Caller should ensure that it is the only one to call this function. This
> +  function cannot be called concurrently.
> +
> +  @param Dev   The NewBus device representing this XenBus bus.
> +
> +  @return      On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
> +               indicating the type of failure.
> +**/
> +XENSTORE_STATUS
> +XenBusEnumerateBus (
> +  XENBUS_DEVICE *Dev
> +  );
> +
> +#endif /* _XEN_XENBUS_XENBUSB_H */

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

* Re: [edk2] [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project.
       [not found]   ` <20141019234732.22698.78740@jljusten-ivy>
  2014-10-20  1:14     ` Andrew Fish
@ 2014-10-20  1:14     ` Andrew Fish
  2014-10-20 13:24     ` Anthony PERARD
  2 siblings, 0 replies; 29+ messages in thread
From: Andrew Fish @ 2014-10-20  1:14 UTC (permalink / raw)
  To: edk2-devel; +Cc: Anthony PERARD, Xen Devel


[-- Attachment #1.1: Type: text/plain, Size: 1949 bytes --]


> On Oct 19, 2014, at 4:47 PM, Jordan Justen <jordan.l.justen@intel.com> wrote:
> 
> On 2014-10-17 10:03:45, Anthony PERARD wrote:
>> This patch imports publics headers in order to use features from Xen
>> like XenStore, PV Block... There is only the necessary header files and
>> there are only a few modifications in order to facilitate future merge of
>> more recent header (that would be necessary to access new features).
>> 
>> There is little modification compared to the original files:
>> - Removed most of the unused part of the headers
>> - Use of ZeroMem() instead of memset()
>> - using #pragma pack(4) for IA32 compilation.
> 
> Usually EDK II uses pack(1) when concerned about structure layout. I'm
> not saying you need to change this, but it does stand out.

#pack(4) is not the same as #pack(1). 

I think the pack(4) will prevent EFI packing rules from conflicting with the Unix packing rules. For EFI a 64-bit item is always aligned on a 64-bit boundary, this is not the case for most Unixes. 

For clang we have to add flags to change the structure packing default rules for i386, and the #pragma pack(4) undoes that change. 

~/work/Compiler>cat pack.c
#include <stdio.h>

//#pragma pack(4)

struct a {
	int       a;
	long long b;
	int       c;
};


int
main ()
{
  struct a *p = (void *)0;
  
  printf ("a 0x%p\n", &p->a);
  printf ("b 0x%p\n", &p->b);
  printf ("b 0x%p\n", &p->c);
  printf ("sizeof a = %lu\n", sizeof(struct a)); 
  return 0;
}
~/work/Compiler>
~/work/Compiler>clang  -arch i386 pack.c
~/work/Compiler>./a.out
a 0x0x0
b 0x0x4
b 0x0xc
sizeof a = 16
~/work/Compiler>clang  -arch i386 pack.c -mms-bitfields
~/work/Compiler>./a.out
a 0x0x0
b 0x0x8
b 0x0x10
sizeof a = 24

Add in #pragma pack(4)

~/work/Compiler>clang  -arch i386 pack.c -mms-bitfields
~/work/Compiler>./a.out
a 0x0x0
b 0x0x4
b 0x0xc
sizeof a = 16

Thanks,

Andrew Fish


[-- Attachment #1.2: Type: text/html, Size: 10699 bytes --]

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

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

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

* Re: [edk2] [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project.
       [not found]   ` <20141019234732.22698.78740@jljusten-ivy>
@ 2014-10-20  1:14     ` Andrew Fish
  2014-10-20  1:14     ` Andrew Fish
  2014-10-20 13:24     ` Anthony PERARD
  2 siblings, 0 replies; 29+ messages in thread
From: Andrew Fish @ 2014-10-20  1:14 UTC (permalink / raw)
  To: edk2-devel; +Cc: Anthony PERARD, Xen Devel


[-- Attachment #1.1: Type: text/plain, Size: 1949 bytes --]


> On Oct 19, 2014, at 4:47 PM, Jordan Justen <jordan.l.justen@intel.com> wrote:
> 
> On 2014-10-17 10:03:45, Anthony PERARD wrote:
>> This patch imports publics headers in order to use features from Xen
>> like XenStore, PV Block... There is only the necessary header files and
>> there are only a few modifications in order to facilitate future merge of
>> more recent header (that would be necessary to access new features).
>> 
>> There is little modification compared to the original files:
>> - Removed most of the unused part of the headers
>> - Use of ZeroMem() instead of memset()
>> - using #pragma pack(4) for IA32 compilation.
> 
> Usually EDK II uses pack(1) when concerned about structure layout. I'm
> not saying you need to change this, but it does stand out.

#pack(4) is not the same as #pack(1). 

I think the pack(4) will prevent EFI packing rules from conflicting with the Unix packing rules. For EFI a 64-bit item is always aligned on a 64-bit boundary, this is not the case for most Unixes. 

For clang we have to add flags to change the structure packing default rules for i386, and the #pragma pack(4) undoes that change. 

~/work/Compiler>cat pack.c
#include <stdio.h>

//#pragma pack(4)

struct a {
	int       a;
	long long b;
	int       c;
};


int
main ()
{
  struct a *p = (void *)0;
  
  printf ("a 0x%p\n", &p->a);
  printf ("b 0x%p\n", &p->b);
  printf ("b 0x%p\n", &p->c);
  printf ("sizeof a = %lu\n", sizeof(struct a)); 
  return 0;
}
~/work/Compiler>
~/work/Compiler>clang  -arch i386 pack.c
~/work/Compiler>./a.out
a 0x0x0
b 0x0x4
b 0x0xc
sizeof a = 16
~/work/Compiler>clang  -arch i386 pack.c -mms-bitfields
~/work/Compiler>./a.out
a 0x0x0
b 0x0x8
b 0x0x10
sizeof a = 24

Add in #pragma pack(4)

~/work/Compiler>clang  -arch i386 pack.c -mms-bitfields
~/work/Compiler>./a.out
a 0x0x0
b 0x0x4
b 0x0xc
sizeof a = 16

Thanks,

Andrew Fish


[-- Attachment #1.2: Type: text/html, Size: 10699 bytes --]

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

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

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

* Re: [edk2] [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project.
       [not found]   ` <20141019234732.22698.78740@jljusten-ivy>
  2014-10-20  1:14     ` Andrew Fish
  2014-10-20  1:14     ` Andrew Fish
@ 2014-10-20 13:24     ` Anthony PERARD
  2 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-20 13:24 UTC (permalink / raw)
  To: Jordan Justen; +Cc: edk2-devel, Xen Devel

On Sun, Oct 19, 2014 at 04:47:32PM -0700, Jordan Justen wrote:
> On 2014-10-17 10:03:45, Anthony PERARD wrote:
> > This patch imports publics headers in order to use features from Xen
> > like XenStore, PV Block... There is only the necessary header files and
> > there are only a few modifications in order to facilitate future merge of
> > more recent header (that would be necessary to access new features).
> > 
> > There is little modification compared to the original files:
> > - Removed most of the unused part of the headers
> > - Use of ZeroMem() instead of memset()
> > - using #pragma pack(4) for IA32 compilation.
> 
> Usually EDK II uses pack(1) when concerned about structure layout. I'm
> not saying you need to change this, but it does stand out.
> 
> > - Replace types to be more UEFI compliant using a script.
> > 
> > OVMF, when built for IA32 arch, uses the gcc switch -malign-double. This
> > change the alignment of fields in some struct compare to what is
> > espected by Xen and any backends. To fix the alignment, the #pragma pack(4)
> > directive is used around the struct that need it.
> > 
> > Command to run to change types:
> > find OvmfPkg/Include/IndustryStandard/Xen -type f -name '*.h' -exec sed
> >   --regexp-extended --file=fix_type_in_xen_includes.sed --in-place {} \;
> 
> Did you intend to include fix_type_in_xen_includes.sed?

No, I did not. I though that having the content of the script in the
commit message would be enough. I guest that I could add a README in to
OvmfPkg/Include/IndustryStandard/Xen, so it will be easier for the next
person to find the information.

> Maybe you could mention the source (url, version) for the files? Was
> it a direct copy into OvmfPkg/Include/IndustryStandard/Xen before
> using the script?
> 
> How easy do you think someone could 'update' the files from Xen based
> on the information you provided here?

I guest it would not be to hard, I've put in this commit message
everything I've done to import the headers.

> > This line is commented instead of been change as I'm not sure why it
> > does not compile (when s/char/CHAR8/), and it does not seems necessary
> > so far.
> >   /* __DEFINE_XEN_GUEST_HANDLE(uchar, unsigned char); */
> 
> Could 'unsigned char' => 'UINT8' help?

I'll give it a try.

> -Jordan
> 
> >   in OvmfPkg/Include/IndustryStandard/Xen/arch-x86/xen.h
> > 
> > Avoid changing the 'long' that is not a type (with the first line).
> > $ cat fix_type_in_xen_includes.sed
> > /as long as/b
> > 
> > s/([^a-zA-Z0-9_]|^)uint8_t([^a-zA-Z0-9_]|$)/\1UINT8\2/g
> > s/([^a-zA-Z0-9_]|^)uint16_t([^a-zA-Z0-9_]|$)/\1UINT16\2/g
> > s/([^a-zA-Z0-9_]|^)uint32_t([^a-zA-Z0-9_]|$)/\1UINT32\2/g
> > s/([^a-zA-Z0-9_]|^)uint64_t([^a-zA-Z0-9_]|$)/\1UINT64\2/g
> > 
> > s/([^a-zA-Z0-9_]|^)int8_t([^a-zA-Z0-9_]|$)/\1INT8\2/g
> > s/([^a-zA-Z0-9_]|^)int16_t([^a-zA-Z0-9_]|$)/\1INT16\2/g
> > s/([^a-zA-Z0-9_]|^)int32_t([^a-zA-Z0-9_]|$)/\1INT32\2/g
> > s/([^a-zA-Z0-9_]|^)int64_t([^a-zA-Z0-9_]|$)/\1INT64\2/g
> > 
> > s/([^a-zA-Z0-9_]|^)void([^a-zA-Z0-9_]|$)/\1VOID\2/g
> > s/([^a-zA-Z0-9_]|^)unsigned int([^a-zA-Z0-9_]|$)/\1UINT32\2/g
> > s/([^a-zA-Z0-9_]|^)int([^a-zA-Z0-9_]|$)/\1INT32\2/g
> > s/([^a-zA-Z0-9_]|^)char([^a-zA-Z0-9_]|$)/\1CHAR8\2/g
> > s/([^a-zA-Z0-9_]|^)unsigned long([^a-zA-Z0-9_]|$)/\1UINTN\2/g
> > s/([^a-zA-Z0-9_]|^)long([^a-zA-Z0-9_]|$)/\1INTN\2/g

-- 
Anthony PERARD

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

* Re: [edk2] [PATCH v3 03/19] OvmfPkg: Add basic skeleton for the XenBus bus driver.
       [not found]   ` <20141019232711.22698.47223@jljusten-ivy>
@ 2014-10-20 13:29     ` Anthony PERARD
  0 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-20 13:29 UTC (permalink / raw)
  To: Jordan Justen; +Cc: edk2-devel, Xen Devel

On Sun, Oct 19, 2014 at 04:27:11PM -0700, Jordan Justen wrote:
> On 2014-10-17 10:03:46, Anthony PERARD wrote:
> > This includes Component Name and Driver Binding.
> > 
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > 
> > ---
> > Change in V3:
> > - enable compilation for Ia32 and Ia32X64
> > - fix version (driver binding)
> > 
> > Change in V2:
> > - Simple support of controller name.
> > - Cleaning up comments, files header.
> > - Add Licenses
> > - Rename XenbusDxe to XenBusDxe.
> > ---
> >  OvmfPkg/OvmfPkgIa32.dsc           |   1 +
> >  OvmfPkg/OvmfPkgIa32.fdf           |   1 +
> >  OvmfPkg/OvmfPkgIa32X64.dsc        |   1 +
> >  OvmfPkg/OvmfPkgIa32X64.fdf        |   1 +
> >  OvmfPkg/OvmfPkgX64.dsc            |   1 +
> >  OvmfPkg/OvmfPkgX64.fdf            |   1 +
> >  OvmfPkg/XenBusDxe/ComponentName.c | 190 +++++++++++++++++++++++
> >  OvmfPkg/XenBusDxe/ComponentName.h | 110 +++++++++++++
> >  OvmfPkg/XenBusDxe/DriverBinding.h | 144 +++++++++++++++++
> >  OvmfPkg/XenBusDxe/XenBusDxe.c     | 317 ++++++++++++++++++++++++++++++++++++++
> >  OvmfPkg/XenBusDxe/XenBusDxe.h     |  93 +++++++++++
> >  OvmfPkg/XenBusDxe/XenBusDxe.inf   |  56 +++++++
> >  12 files changed, 916 insertions(+)
> >  create mode 100644 OvmfPkg/XenBusDxe/ComponentName.c
> >  create mode 100644 OvmfPkg/XenBusDxe/ComponentName.h
> >  create mode 100644 OvmfPkg/XenBusDxe/DriverBinding.h
> >  create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.c
> >  create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.h
> >  create mode 100644 OvmfPkg/XenBusDxe/XenBusDxe.inf
> 
> > diff --git a/OvmfPkg/XenBusDxe/ComponentName.c b/OvmfPkg/XenBusDxe/ComponentName.c
> > new file mode 100644
> > index 0000000..bcf1e51
> > --- /dev/null
> > +++ b/OvmfPkg/XenBusDxe/ComponentName.c
> > @@ -0,0 +1,190 @@
> > +/** @file
> > +  Component Name functions implementation for XenBus Bus driver.
> > +
> > +  Copyright (C) 2014, Citrix Ltd.
> > +
> > +  Redistribution and use in source and binary forms, with or without
> > +  modification, are permitted provided that the following conditions
> > +  are met:
> > +
> > +  * Redistributions of source code must retain the above copyright
> > +    notice, this list of conditions and the following disclaimer.
> > +  * Redistributions in binary form must reproduce the above copyright
> > +    notice, this list of conditions and the following disclaimer in
> > +    the documentation and/or other materials provided with the
> > +    distribution.
> > +
> > +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> > +  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > +  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> > +  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> > +  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> > +  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> > +  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > +  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
> > +  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> > +  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
> > +  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> > +  POSSIBILITY OF SUCH DAMAGE.
> 
> This appears to match the 2-clause BSD license like the rest of EDK
> II. Any reason to not follow the commonly used file header text?

No reason. I'll change that everywhere I've introduce new code.

> """
>   This program and the accompanying materials
>   are licensed and made available under the terms and conditions of the BSD License
>   which accompanies this distribution.  The full text of the license may be found at
>   http://opensource.org/licenses/bsd-license.php
> 
>   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
>   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
> """
> 
> > diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.inf b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> > new file mode 100644
> > index 0000000..25fd2f6
> > --- /dev/null
> > +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
> > @@ -0,0 +1,56 @@
> > +
> > +## @file
> > +#  TODO: Brief Description of UEFI Driver XenBusDxe
> > +#
> > +#  TODO: Detailed Description of UEFI Driver XenBusDxe
> > +#
> > +#  TODO: Copyright for UEFI Driver XenBusDxe
> > +#
> > +#  TODO: License for UEFI Driver XenBusDxe
> 
> It looks like this is still todo by the end of the series.

I will fix this.

-- 
Anthony PERARD

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

* Re: [edk2] [PATCH v3 08/19] OvmfPkg/XenBusDxe: Add InterlockedCompareExchange16.
       [not found]   ` <20141020000013.22698.55324@jljusten-ivy>
@ 2014-10-20 13:37     ` Anthony PERARD
  0 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-20 13:37 UTC (permalink / raw)
  To: Jordan Justen; +Cc: edk2-devel, Xen Devel

On Sun, Oct 19, 2014 at 05:00:13PM -0700, Jordan Justen wrote:
> On 2014-10-17 10:03:51, Anthony PERARD wrote:
> > This patch is inspired by InterlockedCompareExchange32 from the
> > BaseSynchronizationLib.
> 
> Why not attempt to add it to BaseSynchronizationLib?

The BaseSynchronizationLib have assembly for every architecture, it felt
like InterlockedCompareExchange16 would be needed to be done for every
architecture (x86, ARM, ...) to be able to add it to the
BaseSynchronizationLib. So I did not.

Should I redo the patch, and have InterlockedCompareExchange16 only for
IA32 and X64 would be enough?

-- 
Anthony PERARD

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

* Re: [edk2] [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce XenBus support itself.
       [not found]   ` <20141020002045.22698.90635@jljusten-ivy>
@ 2014-10-20 13:41     ` Anthony PERARD
  0 siblings, 0 replies; 29+ messages in thread
From: Anthony PERARD @ 2014-10-20 13:41 UTC (permalink / raw)
  To: Jordan Justen; +Cc: edk2-devel, Xen Devel

On Sun, Oct 19, 2014 at 05:20:45PM -0700, Jordan Justen wrote:
> On 2014-10-17 10:03:58, Anthony PERARD wrote:
> > This is a bus-like on top of XenStore. It will look for advertised
> > ParaVirtualized devices and initialize them by producing XenBus
> > protocol.
> > 
> > Origin: FreeBSD 10.0
> > 
> > License: This patch adds XenBus.c which is under the MIT licence.
> > 
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com>
> > 
> > ---
> > Change in V3:
> > - Insert to ChildList later, once populated.
> > - Remove XENBUS_XENSTORE_NODE macro.
> > - add comment to XenBusAddDevice and XenBusEnumerateBus about
> >   concurrency calls.
> > - Add a description to the introduced member to the protocol.
> > 
> > Change in V2:
> > - comment, file header
> > - Fix comment style
> > - Error handling in the main init function
> > - coding style
> > - Fix error path in add device.
> > ---
> >  OvmfPkg/Include/Protocol/XenBus.h |  19 ++
> >  OvmfPkg/XenBusDxe/XenBus.c        | 372 ++++++++++++++++++++++++++++++++++++++
> >  OvmfPkg/XenBusDxe/XenBus.h        |  64 +++++++
> >  OvmfPkg/XenBusDxe/XenBusDxe.c     |  66 +++++++
> >  OvmfPkg/XenBusDxe/XenBusDxe.h     |  19 ++
> >  OvmfPkg/XenBusDxe/XenBusDxe.inf   |   3 +
> >  6 files changed, 543 insertions(+)
> >  create mode 100644 OvmfPkg/XenBusDxe/XenBus.c
> >  create mode 100644 OvmfPkg/XenBusDxe/XenBus.h
> 
> > diff --git a/OvmfPkg/XenBusDxe/XenBus.h b/OvmfPkg/XenBusDxe/XenBus.h
> > new file mode 100644
> > index 0000000..7ff25c3
> > --- /dev/null
> > +++ b/OvmfPkg/XenBusDxe/XenBus.h
> > @@ -0,0 +1,64 @@
> > +/** @file
> > +  Core definitions and data structures shareable across OS platforms.
> > +
> > +  Copyright (c) 2010 Spectra Logic Corporation
> > +  Copyright (C) 2008 Doug Rabson
> > +  All rights reserved.
> > +  Copyright (C) 2014, Citrix Ltd.
> > +
> > +  Redistribution and use in source and binary forms, with or without
> > +  modification, are permitted provided that the following conditions
> > +  are met:
> > +  1. Redistributions of source code must retain the above copyright
> > +     notice, this list of conditions, and the following disclaimer,
> > +     without modification.
> > +  2. Redistributions in binary form must reproduce at minimum a disclaimer
> > +     substantially similar to the "NO WARRANTY" disclaimer below
> > +     ("Disclaimer") and any redistribution must be conditioned upon
> > +     including a substantially similar Disclaimer requirement for further
> > +     binary redistribution.
> > +
> > +  NO WARRANTY
> > +  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> > +  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > +  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
> > +  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
> > +  HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> > +  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> > +  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > +  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> > +  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> > +  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> > +  POSSIBILITY OF SUCH DAMAGES.
> 
> What is this license?
> 
> The code below appears to have been written just for EDK II, so maybe
> just use the standard EDK II license header?

Yes, there is nothing left from the original file. I will use the
standard license header.

> -Jordan
> 
> > +
> > +**/
> > +#ifndef _XEN_XENBUS_XENBUSB_H
> > +#define _XEN_XENBUS_XENBUSB_H
> > +
> > +#include "XenBusDxe.h"
> > +
> > +#define XENBUS_DEVICE_PATH_TYPE_VBD 0x1
> > +struct _XENBUS_DEVICE_PATH {
> > +  VENDOR_DEVICE_PATH  Vendor;
> > +  UINT8               Type;
> > +  UINT16              DeviceId;
> > +};
> > +
> > +
> > +/**
> > +  Perform XenBus bus enumeration and install protocol for children.
> > +
> > +  Caller should ensure that it is the only one to call this function. This
> > +  function cannot be called concurrently.
> > +
> > +  @param Dev   The NewBus device representing this XenBus bus.
> > +
> > +  @return      On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
> > +               indicating the type of failure.
> > +**/
> > +XENSTORE_STATUS
> > +XenBusEnumerateBus (
> > +  XENBUS_DEVICE *Dev
> > +  );
> > +
> > +#endif /* _XEN_XENBUS_XENBUSB_H */

-- 
Anthony PERARD

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

end of thread, other threads:[~2014-10-20 13:41 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1413565442-29149-1-git-send-email-anthony.perard@citrix.com>
2014-10-17 17:03 ` [PATCH v3 01/19] OvmfPkg: Add the MIT license to License.txt Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 03/19] OvmfPkg: Add basic skeleton for the XenBus bus driver Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 04/19] OvmfPkg/XenBusDxe: Add device state struct and create an ExitBoot services event Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 05/19] OvmfPkg/XenBusDxe: Add support to make Xen Hypercalls Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 06/19] OvmfPkg/XenBusDxe: Open PciIo protocol Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 07/19] OvmfPkg: Introduce XenBus Protocol Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 08/19] OvmfPkg/XenBusDxe: Add InterlockedCompareExchange16 Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 09/19] OvmfPkg/XenBusDxe: Add Grant Table functions Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 10/19] OvmfPkg/XenBusDxe: Add Event Channel Notify Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 11/19] OvmfPkg/XenBusDxe: Add TestAndClearBit Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 12/19] OvmfPkg/XenBusDxe: Add XenStore client implementation Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 13/19] OvmfPkg/XenBusDxe: Add an helper AsciiStrDup Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 14/19] OvmfPkg/XenBusDxe: Add XenStore function into the XenBus protocol Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce XenBus support itself Anthony PERARD
2014-10-17 17:03 ` [PATCH v3 16/19] OvmfPkg/XenBusDxe: Add Event Channel into XenBus protocol Anthony PERARD
2014-10-17 17:04 ` [PATCH v3 17/19] OvmfPkg/XenPvBlkDxe: Xen PV Block device, initial skeleton Anthony PERARD
2014-10-17 17:04 ` [PATCH v3 18/19] OvmfPkg/XenPvBlkDxe: Add BlockFront client Anthony PERARD
2014-10-17 17:04 ` [PATCH v3 19/19] OvmfPkg/XenPvBlkDxe: Add BlockIo Anthony PERARD
     [not found] ` <1413565442-29149-4-git-send-email-anthony.perard@citrix.com>
2014-10-19 23:27   ` [edk2] [PATCH v3 03/19] OvmfPkg: Add basic skeleton for the XenBus bus driver Jordan Justen
     [not found]   ` <20141019232711.22698.47223@jljusten-ivy>
2014-10-20 13:29     ` Anthony PERARD
     [not found] ` <1413565442-29149-3-git-send-email-anthony.perard@citrix.com>
2014-10-19 23:47   ` [edk2] [PATCH v3 02/19] OvmfPkg: Add public headers from Xen Project Jordan Justen
     [not found]   ` <20141019234732.22698.78740@jljusten-ivy>
2014-10-20  1:14     ` Andrew Fish
2014-10-20  1:14     ` Andrew Fish
2014-10-20 13:24     ` Anthony PERARD
     [not found] ` <1413565442-29149-9-git-send-email-anthony.perard@citrix.com>
2014-10-20  0:00   ` [edk2] [PATCH v3 08/19] OvmfPkg/XenBusDxe: Add InterlockedCompareExchange16 Jordan Justen
     [not found]   ` <20141020000013.22698.55324@jljusten-ivy>
2014-10-20 13:37     ` Anthony PERARD
     [not found] ` <1413565442-29149-16-git-send-email-anthony.perard@citrix.com>
2014-10-20  0:20   ` [edk2] [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce XenBus support itself Jordan Justen
     [not found]   ` <20141020002045.22698.90635@jljusten-ivy>
2014-10-20 13:41     ` Anthony PERARD

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