[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 14/18] OvmfPkg/XenBusDxe: Indroduce XenBus support itself.
On Thu, Sep 04, 2014 at 05:51:09PM +0100, 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 > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx> > > --- > 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 | 11 +- > OvmfPkg/XenBusDxe/XenBus.c | 368 > ++++++++++++++++++++++++++++++++++++++ > OvmfPkg/XenBusDxe/XenBus.h | 67 +++++++ > OvmfPkg/XenBusDxe/XenBusDxe.c | 71 ++++++++ > OvmfPkg/XenBusDxe/XenBusDxe.h | 19 ++ > OvmfPkg/XenBusDxe/XenBusDxe.inf | 3 + > 6 files changed, 538 insertions(+), 1 deletion(-) > 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 99e174b..f223be7 100644 > --- a/OvmfPkg/Include/Protocol/XenBus.h > +++ b/OvmfPkg/Include/Protocol/XenBus.h > @@ -45,7 +45,7 @@ > /// > typedef struct _XENBUS_PROTOCOL XENBUS_PROTOCOL; > > -typedef enum xenbus_state XenbusState; > +typedef enum xenbus_state XenBusState; > > typedef struct > { > @@ -138,6 +138,14 @@ XENSTORE_STATUS > ); > > typedef > +XENSTORE_STATUS > +(EFIAPI *XENBUS_SET_STATE)( > + IN XENBUS_PROTOCOL *This, > + IN XENSTORE_TRANSACTION Transaction, > + IN XenBusState State > + ); > + > +typedef > EFI_STATUS > (EFIAPI *XENBUS_GRANT_ACCESS)( > IN XENBUS_PROTOCOL *This, > @@ -196,6 +204,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..2e1f939 > --- /dev/null > +++ b/OvmfPkg/XenBusDxe/XenBus.c > @@ -0,0 +1,368 @@ > +/** @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; > +} > + Could you add a comment here saying that the callers should ensure that they are the only ones calling this function - as this function does not take a lock when adding in the Dev->ChildList > +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), > + XENBUS_XENSTORE_NODE "/%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); > + InsertTailList (&Dev->ChildList, &Private->Link); > + > + 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); Could you move the 'InsertTailList' to be done after the 'Private' has been fully populated? I know that the current caller of this function is only called during initialization - but in the future this could be extended to called multiple times - and if there are two threads - one adding and another reading from Dev->ChildList - the second thread can get incomplete data. > + FreePool (TempXenBusPath); > + > + 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; > + } > + > +out: > + return Status; > +ErrorOpenProtocolByChild: > + gBS->UninstallMultipleProtocolInterfaces ( > + &Private->Handle, > + &gEfiDevicePathProtocolGuid, Private->DevicePath, > + &gXenBusProtocolGuid, &Private->XenBusIo, > + NULL); > +ErrorInstallProtocol: > + FreePool (Private->DevicePath); > + FreePool ((VOID *) Private->XenBusIo.Backend); > + FreePool ((VOID *) Private->XenBusIo.Node); > + FreePool ((VOID *) Private->XenBusIo.Type); > + RemoveEntryList (&Private->Link); > + FreePool (Private); > + 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. .. And the caller needs to ensure it is the only one calling it - or it holds a lock. > + */ > +STATIC > +VOID > +XenBusEnumerateDeviceType ( > + XENBUS_DEVICE *Dev, > + CONST CHAR8 *Type > + ) > +{ > + CONST CHAR8 **Directory; > + UINTN Index; > + UINT32 Count; > + XENSTORE_STATUS Status; > + > + Status = XenStoreListDirectory (XST_NIL, > + XENBUS_XENSTORE_NODE, 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. > + > + @param Dev A XENBUS_DEVICE instance. > + > + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value > + indicating the type of failure. Since this is public, I think it should also perculate the need to hold a lock and not call this concurrently. Or that this function ought to not be called at the same as XenBusDeviceInitialized > + */ > +XENSTORE_STATUS > +XenBusEnumerateBus ( > + XENBUS_DEVICE *Dev > + ) > +{ > + CONST CHAR8 **Types; > + UINTN Index; > + UINT32 Count; > + XENSTORE_STATUS Status; > + > + Status = XenStoreListDirectory (XST_NIL, > + XENBUS_XENSTORE_NODE, "", > + &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 > + ) > +{ > + XENBUS_PRIVATE_DATA *Private; > + enum xenbus_state CurrentState; > + XENSTORE_STATUS Status; > + CHAR8 *Temp; > + > + DEBUG ((EFI_D_INFO, "XenBus: Set state to %d\n", NewState)); > + > + Private = XENBUS_PRIVATE_DATA_FROM_THIS (This); > + > + 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..48e0389 > --- /dev/null > +++ b/OvmfPkg/XenBusDxe/XenBus.h > @@ -0,0 +1,67 @@ > +/** @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; > +}; > + > +/** > + The VM relative path to the XenStore subtree this > + bus attachment manages. Huh? > +**/ > +#define XENBUS_XENSTORE_NODE "device" > + > + > +/** > + Perform XenBus bus enumeration and install protocol for childs. childs? children? > + > + @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 76ea67c..50090ba 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" > > > /// > @@ -301,6 +302,7 @@ XenBusDxeDriverBindingStart ( > EFI_PCI_IO_PROTOCOL *PciIo; > EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc; > UINT64 MmioAddr; > + EFI_DEVICE_PATH_PROTOCOL *DevicePath; > > Status = gBS->OpenProtocol ( > ControllerHandle, > @@ -314,12 +316,32 @@ 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); > > + // > + // 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); > @@ -348,6 +370,8 @@ XenBusDxeDriverBindingStart ( > Status = XenStoreInit (Dev); > ASSERT_EFI_ERROR (Status); > > + XenBusEnumerateBus (Dev); > + > Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK, > NotifyExitBoot, > (VOID*) Dev, > @@ -359,6 +383,9 @@ XenBusDxeDriverBindingStart ( > > ErrorNoHyperpage: > FreePool (Dev); > + gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, > + This->DriverBindingHandle, ControllerHandle); > +ErrorOpenningProtocol: > gBS->CloseProtocol (ControllerHandle, &gEfiPciIoProtocolGuid, > This->DriverBindingHandle, ControllerHandle); > return Status; > @@ -399,12 +426,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); > return EFI_SUCCESS; > diff --git a/OvmfPkg/XenBusDxe/XenBusDxe.h b/OvmfPkg/XenBusDxe/XenBusDxe.h > index dc48a46..7213184 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 9052967..c326bcf 100644 > --- a/OvmfPkg/XenBusDxe/XenBusDxe.inf > +++ b/OvmfPkg/XenBusDxe/XenBusDxe.inf > @@ -40,6 +40,9 @@ > EventChannel.h > XenStore.c > XenStore.h > + XenBus.c > + XenBus.h > + Helpers.c > > [Sources.X64] > X64/hypercall.S > -- > Anthony PERARD > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@xxxxxxxxxxxxx > http://lists.xen.org/xen-devel _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |