Generated mechanically with:
find OvmfPkg -type f -exec sed -i -e 's/EFI_D_/DEBUG_/g' {} \;
Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
Cc: Philippe Mathieu-Daude <philmd@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Message-Id: <20200429215327.606467-1-rebecca@bsdio.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
		
	
		
			
				
	
	
		
			371 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			371 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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 <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
 | 
						|
    {                                               // 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
 | 
						|
};
 |