summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnthony PERARD <anthony.perard@citrix.com>2014-10-29 06:51:18 +0000
committerjljusten <jljusten@Edk2>2014-10-29 06:51:18 +0000
commit86d968e05ee062b10fe8d597b34f5eab2e2878bd (patch)
tree8c950699bbd77f9bc8bc4ad2dce3aed7568ca78a
parentc23c037fb3b47574950a19d4753fbeccff5e3d42 (diff)
downloadedk2-86d968e05ee062b10fe8d597b34f5eab2e2878bd.tar.gz
edk2-86d968e05ee062b10fe8d597b34f5eab2e2878bd.tar.bz2
edk2-86d968e05ee062b10fe8d597b34f5eab2e2878bd.zip
OvmfPkg/XenBusDxe: Introduce XenBus support itself.
This is a bus-like on top of XenStore. It will look for advertised ParaVirtualized devices and initialize them by producing XenBus protocol. Change in V4: - Replace the license by the commonly used file header text. - Clean XenBus.h header (remove copyright that does not belong to the file anymore; and rewrite the brief description of the file) - Fix description on the function 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. 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> Acked-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16270 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--OvmfPkg/Include/Protocol/XenBus.h19
-rw-r--r--OvmfPkg/XenBusDxe/XenBus.c372
-rw-r--r--OvmfPkg/XenBusDxe/XenBus.h44
-rw-r--r--OvmfPkg/XenBusDxe/XenBusDxe.c66
-rw-r--r--OvmfPkg/XenBusDxe/XenBusDxe.h19
-rw-r--r--OvmfPkg/XenBusDxe/XenBusDxe.inf3
6 files changed, 523 insertions, 0 deletions
diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h
index 5693b3f284..8d1fb52c22 100644
--- a/OvmfPkg/Include/Protocol/XenBus.h
+++ b/OvmfPkg/Include/Protocol/XenBus.h
@@ -199,6 +199,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.
@@ -322,6 +340,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 0000000000..edd2d95217
--- /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 0000000000..e96439ab7b
--- /dev/null
+++ b/OvmfPkg/XenBusDxe/XenBus.h
@@ -0,0 +1,44 @@
+/** @file
+ XenBus Bus driver declarations.
+
+ Copyright (C) 2014, Citrix Ltd.
+
+ 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.
+
+**/
+#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 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
+ );
+
+#endif /* _XEN_XENBUS_XENBUSB_H */
diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.c b/OvmfPkg/XenBusDxe/XenBusDxe.c
index 679fe3b592..7a7fd82d55 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.c
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.c
@@ -32,6 +32,7 @@
#include "XenHypercall.h"
#include "GrantTable.h"
#include "XenStore.h"
+#include "XenBus.h"
///
@@ -286,6 +287,7 @@ XenBusDxeDriverBindingStart (
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
UINT64 MmioAddr;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
Status = gBS->OpenProtocol (
ControllerHandle,
@@ -299,11 +301,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) {
@@ -350,6 +367,8 @@ XenBusDxeDriverBindingStart (
Status = XenStoreInit (Dev);
ASSERT_EFI_ERROR (Status);
+ XenBusEnumerateBus (Dev);
+
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
NotifyExitBoot,
(VOID*) Dev,
@@ -360,6 +379,9 @@ XenBusDxeDriverBindingStart (
ErrorAllocated:
FreePool (Dev);
+ gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle, ControllerHandle);
+ErrorOpenningProtocol:
gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid,
This->DriverBindingHandle, ControllerHandle);
return Status;
@@ -400,12 +422,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 6be5c58d92..11640223eb 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.h
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.h
@@ -82,6 +82,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.
@@ -92,11 +93,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 1343808ae3..17a5a9073a 100644
--- a/OvmfPkg/XenBusDxe/XenBusDxe.inf
+++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf
@@ -44,6 +44,9 @@
EventChannel.h
XenStore.c
XenStore.h
+ XenBus.c
+ XenBus.h
+ Helpers.c
[Sources.IA32]
Ia32/hypercall.S