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

[Xen-devel] [PATCH v3 15/19] OvmfPkg/XenBusDxe: Indroduce 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.

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@xxxxxxxxxx>

---
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


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


 


Rackspace

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