From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- roms/edk2/OvmfPkg/XenBusDxe/XenBus.c | 370 +++++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 roms/edk2/OvmfPkg/XenBusDxe/XenBus.c (limited to 'roms/edk2/OvmfPkg/XenBusDxe/XenBus.c') diff --git a/roms/edk2/OvmfPkg/XenBusDxe/XenBus.c b/roms/edk2/OvmfPkg/XenBusDxe/XenBus.c new file mode 100644 index 000000000..f8a41b6d3 --- /dev/null +++ b/roms/edk2/OvmfPkg/XenBusDxe/XenBus.c @@ -0,0 +1,370 @@ +/** @file + XenBus Bus driver implementation. + + 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: + + SPDX-License-Identifier: MIT +**/ + +#include + +#include "XenBus.h" +#include "GrantTable.h" +#include "XenStore.h" +#include "EventChannel.h" + +#include + +STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData; + +STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate = { + { // Vendor + { // Vendor.Header + HARDWARE_DEVICE_PATH, // Vendor.Header.Type + HW_VENDOR_DP, // Vendor.Header.SubType + { + (UINT8) (sizeof (XENBUS_DEVICE_PATH)), // Vendor.Header.Length[0] + (UINT8) (sizeof (XENBUS_DEVICE_PATH) >> 8), // Vendor.Header.Length[1] + } + }, + XENBUS_PROTOCOL_GUID, // Vendor.Guid + }, + 0, // Type + 0 // DeviceId +}; + + +/** + 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 *ChildXenIo; + + 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 ((DEBUG_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 ((DEBUG_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 = (UINT16)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, + &gXenIoProtocolGuid, + &ChildXenIo, Dev->This->DriverBindingHandle, + Private->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "open by child controller fail (%r)\n", + Status)); + goto ErrorOpenProtocolByChild; + } + } else { + DEBUG ((DEBUG_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 ((VOID*)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 ((VOID*)Types); + + return XENSTORE_STATUS_SUCCESS; +} + +STATIC +XENSTORE_STATUS +EFIAPI +XenBusSetState ( + IN XENBUS_PROTOCOL *This, + IN CONST XENSTORE_TRANSACTION *Transaction, + IN enum xenbus_state NewState + ) +{ + enum xenbus_state CurrentState; + XENSTORE_STATUS Status; + CHAR8 *Temp; + + DEBUG ((DEBUG_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 ((DEBUG_ERROR, "XenBus: failed to write new state\n")); + goto Out; + } + DEBUG ((DEBUG_INFO, "XenBus: Set state to %d, done\n", NewState)); + +Out: + return Status; +} + +STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = { + XENBUS_PRIVATE_DATA_SIGNATURE, // Signature + { NULL, NULL }, // Link + NULL, // Handle + { // XenBusIo + XenBusXenStoreRead, // XenBusIo.XsRead + XenBusXenStoreBackendRead, // XenBusIo.XsBackendRead + XenBusXenStoreSPrint, // XenBusIo.XsPrintf + XenBusXenStoreRemove, // XenBusIo.XsRemove + XenBusXenStoreTransactionStart, // XenBusIo.XsTransactionStart + XenBusXenStoreTransactionEnd, // XenBusIo.XsTransactionEnd + XenBusSetState, // XenBusIo.SetState + XenBusGrantAccess, // XenBusIo.GrantAccess + XenBusGrantEndAccess, // XenBusIo.GrantEndAccess + XenBusEventChannelAllocate, // XenBusIo.EventChannelAllocate + XenBusEventChannelNotify, // XenBusIo.EventChannelNotify + XenBusEventChannelClose, // XenBusIo.EventChannelClose + XenBusRegisterWatch, // XenBusIo.RegisterWatch + XenBusRegisterWatchBackend, // XenBusIo.RegisterWatchBackend + XenBusUnregisterWatch, // XenBusIo.UnregisterWatch + XenBusWaitForWatch, // XenBusIo.WaitForWatch + + NULL, // XenBusIo.Type + 0, // XenBusIo.DeviceId + NULL, // XenBusIo.Node + NULL, // XenBusIo.Backend + }, + + NULL, // Dev + NULL // DevicePath +}; -- cgit 1.2.3-korg