REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the OvmfPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Andrew Fish <afish@apple.com>
		
			
				
	
	
		
			1613 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1613 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Low-level kernel interface to the XenStore.
 | 
						|
 | 
						|
  The XenStore interface is a simple storage system that is a means of
 | 
						|
  communicating state and configuration data between the Xen Domain 0
 | 
						|
  and the various guest domains.  All configuration data other than
 | 
						|
  a small amount of essential information required during the early
 | 
						|
  boot process of launching a Xen aware guest, is managed using the
 | 
						|
  XenStore.
 | 
						|
 | 
						|
  The XenStore is ASCII string based, and has a structure and semantics
 | 
						|
  similar to a filesystem.  There are files and directories, the directories
 | 
						|
  able to contain files or other directories.  The depth of the hierarchy
 | 
						|
  is only limited by the XenStore's maximum path length.
 | 
						|
 | 
						|
  The communication channel between the XenStore service and other
 | 
						|
  domains is via two, guest specific, ring buffers in a shared memory
 | 
						|
  area.  One ring buffer is used for communicating in each direction.
 | 
						|
  The grant table references for this shared memory are given to the
 | 
						|
  guest either via the xen_start_info structure for a fully para-
 | 
						|
  virtualized guest, or via HVM hypercalls for a hardware virtualized
 | 
						|
  guest.
 | 
						|
 | 
						|
  The XenStore communication relies on an event channel and thus
 | 
						|
  interrupts.  But under OVMF this XenStore client will pull the
 | 
						|
  state of the event channel.
 | 
						|
 | 
						|
  Several Xen services depend on the XenStore, most notably the
 | 
						|
  XenBus used to discover and manage Xen devices.
 | 
						|
 | 
						|
  Copyright (C) 2005 Rusty Russell, IBM Corporation
 | 
						|
  Copyright (C) 2009,2010 Spectra Logic Corporation
 | 
						|
  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 "XenStore.h"
 | 
						|
 | 
						|
#include <Library/PrintLib.h>
 | 
						|
 | 
						|
#include <IndustryStandard/Xen/hvm/params.h>
 | 
						|
 | 
						|
#include "EventChannel.h"
 | 
						|
#include <Library/XenHypercallLib.h>
 | 
						|
 | 
						|
//
 | 
						|
// Private Data Structures
 | 
						|
//
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  CONST VOID    *Data;
 | 
						|
  UINT32        Len;
 | 
						|
} WRITE_REQUEST;
 | 
						|
 | 
						|
/* Register callback to watch subtree (node) in the XenStore. */
 | 
						|
#define XENSTORE_WATCH_SIGNATURE  SIGNATURE_32 ('X','S','w','a')
 | 
						|
struct _XENSTORE_WATCH {
 | 
						|
  UINT32        Signature;
 | 
						|
  LIST_ENTRY    Link;
 | 
						|
 | 
						|
  /* Path being watched. */
 | 
						|
  CHAR8         *Node;
 | 
						|
};
 | 
						|
 | 
						|
#define XENSTORE_WATCH_FROM_LINK(l) \
 | 
						|
  CR (l, XENSTORE_WATCH, Link, XENSTORE_WATCH_SIGNATURE)
 | 
						|
 | 
						|
/**
 | 
						|
 * Structure capturing messages received from the XenStore service.
 | 
						|
 */
 | 
						|
#define XENSTORE_MESSAGE_SIGNATURE  SIGNATURE_32 ('X', 'S', 's', 'm')
 | 
						|
typedef struct {
 | 
						|
  UINT32                Signature;
 | 
						|
  LIST_ENTRY            Link;
 | 
						|
 | 
						|
  struct xsd_sockmsg    Header;
 | 
						|
 | 
						|
  union {
 | 
						|
    /* Queued replies. */
 | 
						|
    struct {
 | 
						|
      CHAR8    *Body;
 | 
						|
    } Reply;
 | 
						|
 | 
						|
    /* Queued watch events. */
 | 
						|
    struct {
 | 
						|
      XENSTORE_WATCH    *Handle;
 | 
						|
      CONST CHAR8       **Vector;
 | 
						|
      UINT32            VectorSize;
 | 
						|
    } Watch;
 | 
						|
  } u;
 | 
						|
} XENSTORE_MESSAGE;
 | 
						|
#define XENSTORE_MESSAGE_FROM_LINK(r) \
 | 
						|
  CR (r, XENSTORE_MESSAGE, Link, XENSTORE_MESSAGE_SIGNATURE)
 | 
						|
 | 
						|
/**
 | 
						|
 * Container for all XenStore related state.
 | 
						|
 */
 | 
						|
typedef struct {
 | 
						|
  /**
 | 
						|
   * Pointer to shared memory communication structures allowing us
 | 
						|
   * to communicate with the XenStore service.
 | 
						|
   */
 | 
						|
  struct xenstore_domain_interface    *XenStore;
 | 
						|
 | 
						|
  XENBUS_DEVICE                       *Dev;
 | 
						|
 | 
						|
  /**
 | 
						|
   * A list of replies to our requests.
 | 
						|
   *
 | 
						|
   * The reply list is filled by xs_rcv_thread().  It
 | 
						|
   * is consumed by the context that issued the request
 | 
						|
   * to which a reply is made.  The requester blocks in
 | 
						|
   * XenStoreReadReply ().
 | 
						|
   *
 | 
						|
   * /note Only one requesting context can be active at a time.
 | 
						|
   */
 | 
						|
  LIST_ENTRY       ReplyList;
 | 
						|
 | 
						|
  /** Lock protecting the reply list. */
 | 
						|
  EFI_LOCK         ReplyLock;
 | 
						|
 | 
						|
  /**
 | 
						|
   * List of registered watches.
 | 
						|
   */
 | 
						|
  LIST_ENTRY       RegisteredWatches;
 | 
						|
 | 
						|
  /** Lock protecting the registered watches list. */
 | 
						|
  EFI_LOCK         RegisteredWatchesLock;
 | 
						|
 | 
						|
  /**
 | 
						|
   * List of pending watch callback events.
 | 
						|
   */
 | 
						|
  LIST_ENTRY       WatchEvents;
 | 
						|
 | 
						|
  /** Lock protecting the watch callback list. */
 | 
						|
  EFI_LOCK         WatchEventsLock;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The event channel for communicating with the
 | 
						|
   * XenStore service.
 | 
						|
   */
 | 
						|
  evtchn_port_t    EventChannel;
 | 
						|
 | 
						|
  /** Handle for XenStore events. */
 | 
						|
  EFI_EVENT        EventChannelEvent;
 | 
						|
} XENSTORE_PRIVATE;
 | 
						|
 | 
						|
//
 | 
						|
// Global Data
 | 
						|
//
 | 
						|
static XENSTORE_PRIVATE  xs;
 | 
						|
 | 
						|
//
 | 
						|
// Private Utility Functions
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Count and optionally record pointers to a number of NUL terminated
 | 
						|
  strings in a buffer.
 | 
						|
 | 
						|
  @param Strings  A pointer to a contiguous buffer of NUL terminated strings.
 | 
						|
  @param Len      The length of the buffer pointed to by strings.
 | 
						|
  @param Dst      An array to store pointers to each string found in strings.
 | 
						|
 | 
						|
  @return  A count of the number of strings found.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINT32
 | 
						|
ExtractStrings (
 | 
						|
  IN  CONST CHAR8  *Strings,
 | 
						|
  IN  UINTN        Len,
 | 
						|
  OUT CONST CHAR8  **Dst OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32       Num = 0;
 | 
						|
  CONST CHAR8  *Ptr;
 | 
						|
 | 
						|
  for (Ptr = Strings; Ptr < Strings + Len; Ptr += AsciiStrSize (Ptr)) {
 | 
						|
    if (Dst != NULL) {
 | 
						|
      *Dst++ = Ptr;
 | 
						|
    }
 | 
						|
 | 
						|
    Num++;
 | 
						|
  }
 | 
						|
 | 
						|
  return Num;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert a contiguous buffer containing a series of NUL terminated
 | 
						|
  strings into an array of pointers to strings.
 | 
						|
 | 
						|
  The returned pointer references the array of string pointers which
 | 
						|
  is followed by the storage for the string data.  It is the client's
 | 
						|
  responsibility to free this storage.
 | 
						|
 | 
						|
  The storage addressed by Strings is free'd prior to Split returning.
 | 
						|
 | 
						|
  @param Strings  A pointer to a contiguous buffer of NUL terminated strings.
 | 
						|
  @param Len      The length of the buffer pointed to by strings.
 | 
						|
  @param NumPtr   The number of strings found and returned in the strings
 | 
						|
                  array.
 | 
						|
 | 
						|
  @return  An array of pointers to the strings found in the input buffer.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
CONST CHAR8 **
 | 
						|
Split (
 | 
						|
  IN  CHAR8   *Strings,
 | 
						|
  IN  UINTN   Len,
 | 
						|
  OUT UINT32  *NumPtr
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST CHAR8  **Dst;
 | 
						|
 | 
						|
  ASSERT (NumPtr != NULL);
 | 
						|
  ASSERT (Strings != NULL);
 | 
						|
 | 
						|
  /* Protect against unterminated buffers. */
 | 
						|
  if (Len > 0) {
 | 
						|
    Strings[Len - 1] = '\0';
 | 
						|
  }
 | 
						|
 | 
						|
  /* Count the Strings. */
 | 
						|
  *NumPtr = ExtractStrings (Strings, Len, NULL);
 | 
						|
 | 
						|
  /* Transfer to one big alloc for easy freeing by the caller. */
 | 
						|
  Dst = AllocatePool (*NumPtr * sizeof (CHAR8 *) + Len);
 | 
						|
  CopyMem ((VOID *)&Dst[*NumPtr], Strings, Len);
 | 
						|
  FreePool (Strings);
 | 
						|
 | 
						|
  /* Extract pointers to newly allocated array. */
 | 
						|
  Strings = (CHAR8 *)&Dst[*NumPtr];
 | 
						|
  ExtractStrings (Strings, Len, Dst);
 | 
						|
 | 
						|
  return (Dst);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Convert from watch token (unique identifier) to the associated
 | 
						|
  internal tracking structure for this watch.
 | 
						|
 | 
						|
  @param Tocken  The unique identifier for the watch to find.
 | 
						|
 | 
						|
  @return  A pointer to the found watch structure or NULL.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_WATCH *
 | 
						|
XenStoreFindWatch (
 | 
						|
  IN CONST CHAR8  *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  XENSTORE_WATCH  *Watch, *WantedWatch;
 | 
						|
  LIST_ENTRY      *Entry;
 | 
						|
 | 
						|
  WantedWatch = (VOID *)AsciiStrHexToUintn (Token);
 | 
						|
 | 
						|
  if (IsListEmpty (&xs.RegisteredWatches)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Entry = GetFirstNode (&xs.RegisteredWatches);
 | 
						|
       !IsNull (&xs.RegisteredWatches, Entry);
 | 
						|
       Entry = GetNextNode (&xs.RegisteredWatches, Entry))
 | 
						|
  {
 | 
						|
    Watch = XENSTORE_WATCH_FROM_LINK (Entry);
 | 
						|
    if (Watch == WantedWatch) {
 | 
						|
      return Watch;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Public Utility Functions
 | 
						|
// API comments for these methods can be found in XenStore.h
 | 
						|
//
 | 
						|
 | 
						|
CHAR8 *
 | 
						|
XenStoreJoin (
 | 
						|
  IN CONST CHAR8  *DirectoryPath,
 | 
						|
  IN CONST CHAR8  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8  *Buf;
 | 
						|
  UINTN  BufSize;
 | 
						|
 | 
						|
  /* +1 for '/' and +1 for '\0' */
 | 
						|
  BufSize = AsciiStrLen (DirectoryPath) + AsciiStrLen (Node) + 2;
 | 
						|
  Buf     = AllocatePool (BufSize);
 | 
						|
  ASSERT (Buf != NULL);
 | 
						|
 | 
						|
  if (Node[0] == '\0') {
 | 
						|
    AsciiSPrint (Buf, BufSize, "%a", DirectoryPath);
 | 
						|
  } else {
 | 
						|
    AsciiSPrint (Buf, BufSize, "%a/%a", DirectoryPath, Node);
 | 
						|
  }
 | 
						|
 | 
						|
  return Buf;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Low Level Communication Management
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Verify that the indexes for a ring are valid.
 | 
						|
 | 
						|
  The difference between the producer and consumer cannot
 | 
						|
  exceed the size of the ring.
 | 
						|
 | 
						|
  @param Cons  The consumer index for the ring to test.
 | 
						|
  @param Prod  The producer index for the ring to test.
 | 
						|
 | 
						|
  @retval TRUE   If indexes are in range.
 | 
						|
  @retval FALSE  If the indexes are out of range.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
XenStoreCheckIndexes (
 | 
						|
  XENSTORE_RING_IDX  Cons,
 | 
						|
  XENSTORE_RING_IDX  Prod
 | 
						|
  )
 | 
						|
{
 | 
						|
  return ((Prod - Cons) <= XENSTORE_RING_SIZE);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return a pointer to, and the length of, the contiguous
 | 
						|
  free region available for output in a ring buffer.
 | 
						|
 | 
						|
  @param Cons    The consumer index for the ring.
 | 
						|
  @param Prod    The producer index for the ring.
 | 
						|
  @param Buffer  The base address of the ring's storage.
 | 
						|
  @param LenPtr  The amount of contiguous storage available.
 | 
						|
 | 
						|
  @return  A pointer to the start location of the free region.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID *
 | 
						|
XenStoreGetOutputChunk (
 | 
						|
  IN  XENSTORE_RING_IDX  Cons,
 | 
						|
  IN  XENSTORE_RING_IDX  Prod,
 | 
						|
  IN  CHAR8              *Buffer,
 | 
						|
  OUT UINT32             *LenPtr
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  Len;
 | 
						|
 | 
						|
  Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Prod);
 | 
						|
  if ((XENSTORE_RING_SIZE - (Prod - Cons)) < Len) {
 | 
						|
    Len = XENSTORE_RING_SIZE - (Prod - Cons);
 | 
						|
  }
 | 
						|
 | 
						|
  *LenPtr = Len;
 | 
						|
  return (Buffer + MASK_XENSTORE_IDX (Prod));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return a pointer to, and the length of, the contiguous
 | 
						|
  data available to read from a ring buffer.
 | 
						|
 | 
						|
  @param Cons    The consumer index for the ring.
 | 
						|
  @param Prod    The producer index for the ring.
 | 
						|
  @param Buffer  The base address of the ring's storage.
 | 
						|
  @param LenPtr  The amount of contiguous data available to read.
 | 
						|
 | 
						|
  @return  A pointer to the start location of the available data.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
CONST VOID *
 | 
						|
XenStoreGetInputChunk (
 | 
						|
  IN  XENSTORE_RING_IDX  Cons,
 | 
						|
  IN  XENSTORE_RING_IDX  Prod,
 | 
						|
  IN  CONST CHAR8        *Buffer,
 | 
						|
  OUT UINT32             *LenPtr
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  Len;
 | 
						|
 | 
						|
  Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Cons);
 | 
						|
  if ((Prod - Cons) < Len) {
 | 
						|
    Len = Prod - Cons;
 | 
						|
  }
 | 
						|
 | 
						|
  *LenPtr = Len;
 | 
						|
  return (Buffer + MASK_XENSTORE_IDX (Cons));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Wait for an event or timeout.
 | 
						|
 | 
						|
  @param Event    Event to wait for.
 | 
						|
  @param Timeout  A timeout value in 100ns units.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   Event have been triggered or the current TPL is not
 | 
						|
                        TPL_APPLICATION.
 | 
						|
  @retval EFI_TIMEOUT   Timeout have expired.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
XenStoreWaitForEvent (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN UINT64     Timeout
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN       Index;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  EFI_EVENT   TimerEvent;
 | 
						|
  EFI_EVENT   WaitList[2];
 | 
						|
 | 
						|
  gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
 | 
						|
  gBS->SetTimer (TimerEvent, TimerRelative, Timeout);
 | 
						|
 | 
						|
  WaitList[0] = xs.EventChannelEvent;
 | 
						|
  WaitList[1] = TimerEvent;
 | 
						|
  Status      = gBS->WaitForEvent (2, WaitList, &Index);
 | 
						|
  ASSERT (Status != EFI_INVALID_PARAMETER);
 | 
						|
  gBS->CloseEvent (TimerEvent);
 | 
						|
  if (Status == EFI_UNSUPPORTED) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Index == 1) {
 | 
						|
    return EFI_TIMEOUT;
 | 
						|
  } else {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Transmit data to the XenStore service.
 | 
						|
 | 
						|
  The buffer pointed to by DataPtr is at least Len bytes in length.
 | 
						|
 | 
						|
  @param DataPtr  A pointer to the contiguous data to send.
 | 
						|
  @param Len      The amount of data to send.
 | 
						|
 | 
						|
  @return  On success 0, otherwise an errno value indicating the
 | 
						|
           cause of failure.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreWriteStore (
 | 
						|
  IN CONST VOID  *DataPtr,
 | 
						|
  IN UINT32      Len
 | 
						|
  )
 | 
						|
{
 | 
						|
  XENSTORE_RING_IDX  Cons, Prod;
 | 
						|
  CONST CHAR8        *Data = (CONST CHAR8 *)DataPtr;
 | 
						|
 | 
						|
  while (Len != 0) {
 | 
						|
    void    *Dest;
 | 
						|
    UINT32  Available;
 | 
						|
 | 
						|
    Cons = xs.XenStore->req_cons;
 | 
						|
    Prod = xs.XenStore->req_prod;
 | 
						|
    if ((Prod - Cons) == XENSTORE_RING_SIZE) {
 | 
						|
      /*
 | 
						|
       * Output ring is full. Wait for a ring event.
 | 
						|
       *
 | 
						|
       * Note that the events from both queues are combined, so being woken
 | 
						|
       * does not guarantee that data exist in the read ring.
 | 
						|
       */
 | 
						|
      EFI_STATUS  Status;
 | 
						|
 | 
						|
      Status = XenStoreWaitForEvent (
 | 
						|
                 xs.EventChannelEvent,
 | 
						|
                 EFI_TIMER_PERIOD_SECONDS (1)
 | 
						|
                 );
 | 
						|
      if (Status == EFI_TIMEOUT) {
 | 
						|
        DEBUG ((DEBUG_WARN, "XenStore Write, waiting for a ring event.\n"));
 | 
						|
      }
 | 
						|
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Verify queue sanity. */
 | 
						|
    if (!XenStoreCheckIndexes (Cons, Prod)) {
 | 
						|
      xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
 | 
						|
      return XENSTORE_STATUS_EIO;
 | 
						|
    }
 | 
						|
 | 
						|
    Dest = XenStoreGetOutputChunk (Cons, Prod, xs.XenStore->req, &Available);
 | 
						|
    if (Available > Len) {
 | 
						|
      Available = Len;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (Dest, Data, Available);
 | 
						|
    Data += Available;
 | 
						|
    Len  -= Available;
 | 
						|
 | 
						|
    /*
 | 
						|
     * The store to the producer index, which indicates
 | 
						|
     * to the other side that new data has arrived, must
 | 
						|
     * be visible only after our copy of the data into the
 | 
						|
     * ring has completed.
 | 
						|
     */
 | 
						|
    MemoryFence ();
 | 
						|
    xs.XenStore->req_prod += Available;
 | 
						|
 | 
						|
    /*
 | 
						|
     * The other side will see the change to req_prod at the time of the
 | 
						|
     * interrupt.
 | 
						|
     */
 | 
						|
    MemoryFence ();
 | 
						|
    XenEventChannelNotify (xs.Dev, xs.EventChannel);
 | 
						|
  }
 | 
						|
 | 
						|
  return XENSTORE_STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Receive data from the XenStore service.
 | 
						|
 | 
						|
  The buffer pointed to by DataPtr is at least Len bytes in length.
 | 
						|
 | 
						|
  @param DataPtr  A pointer to the contiguous buffer to receive the data.
 | 
						|
  @param Len      The amount of data to receive.
 | 
						|
 | 
						|
  @return  On success 0, otherwise an errno value indicating the
 | 
						|
           cause of failure.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreReadStore (
 | 
						|
  OUT VOID    *DataPtr,
 | 
						|
  IN  UINT32  Len
 | 
						|
  )
 | 
						|
{
 | 
						|
  XENSTORE_RING_IDX  Cons, Prod;
 | 
						|
  CHAR8              *Data = (CHAR8 *)DataPtr;
 | 
						|
 | 
						|
  while (Len != 0) {
 | 
						|
    UINT32       Available;
 | 
						|
    CONST CHAR8  *Src;
 | 
						|
 | 
						|
    Cons = xs.XenStore->rsp_cons;
 | 
						|
    Prod = xs.XenStore->rsp_prod;
 | 
						|
    if (Cons == Prod) {
 | 
						|
      /*
 | 
						|
       * Nothing to read. Wait for a ring event.
 | 
						|
       *
 | 
						|
       * Note that the events from both queues are combined, so being woken
 | 
						|
       * does not guarantee that data exist in the read ring.
 | 
						|
       */
 | 
						|
      EFI_STATUS  Status;
 | 
						|
 | 
						|
      Status = XenStoreWaitForEvent (
 | 
						|
                 xs.EventChannelEvent,
 | 
						|
                 EFI_TIMER_PERIOD_SECONDS (1)
 | 
						|
                 );
 | 
						|
      if (Status == EFI_TIMEOUT) {
 | 
						|
        DEBUG ((DEBUG_WARN, "XenStore Read, waiting for a ring event.\n"));
 | 
						|
      }
 | 
						|
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    /* Verify queue sanity. */
 | 
						|
    if (!XenStoreCheckIndexes (Cons, Prod)) {
 | 
						|
      xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
 | 
						|
      return XENSTORE_STATUS_EIO;
 | 
						|
    }
 | 
						|
 | 
						|
    Src = XenStoreGetInputChunk (Cons, Prod, xs.XenStore->rsp, &Available);
 | 
						|
    if (Available > Len) {
 | 
						|
      Available = Len;
 | 
						|
    }
 | 
						|
 | 
						|
    /*
 | 
						|
     * Insure the data we read is related to the indexes
 | 
						|
     * we read above.
 | 
						|
     */
 | 
						|
    MemoryFence ();
 | 
						|
 | 
						|
    CopyMem (Data, Src, Available);
 | 
						|
    Data += Available;
 | 
						|
    Len  -= Available;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Insure that the producer of this ring does not see
 | 
						|
     * the ring space as free until after we have copied it
 | 
						|
     * out.
 | 
						|
     */
 | 
						|
    MemoryFence ();
 | 
						|
    xs.XenStore->rsp_cons += Available;
 | 
						|
 | 
						|
    /*
 | 
						|
     * The producer will see the updated consumer index when the event is
 | 
						|
     * delivered.
 | 
						|
     */
 | 
						|
    MemoryFence ();
 | 
						|
    XenEventChannelNotify (xs.Dev, xs.EventChannel);
 | 
						|
  }
 | 
						|
 | 
						|
  return XENSTORE_STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Received Message Processing
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Block reading the next message from the XenStore service and
 | 
						|
  process the result.
 | 
						|
 | 
						|
  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno value
 | 
						|
           indicating the type of failure encountered.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreProcessMessage (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  XENSTORE_MESSAGE  *Message;
 | 
						|
  CHAR8             *Body;
 | 
						|
  XENSTORE_STATUS   Status;
 | 
						|
 | 
						|
  Message            = AllocateZeroPool (sizeof (XENSTORE_MESSAGE));
 | 
						|
  Message->Signature = XENSTORE_MESSAGE_SIGNATURE;
 | 
						|
  Status             = XenStoreReadStore (&Message->Header, sizeof (Message->Header));
 | 
						|
  if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
    FreePool (Message);
 | 
						|
    DEBUG ((DEBUG_ERROR, "XenStore: Error read store (%d)\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Body   = AllocatePool (Message->Header.len + 1);
 | 
						|
  Status = XenStoreReadStore (Body, Message->Header.len);
 | 
						|
  if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
    FreePool (Body);
 | 
						|
    FreePool (Message);
 | 
						|
    DEBUG ((DEBUG_ERROR, "XenStore: Error read store (%d)\n", Status));
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Body[Message->Header.len] = '\0';
 | 
						|
 | 
						|
  if (Message->Header.type == XS_WATCH_EVENT) {
 | 
						|
    Message->u.Watch.Vector = Split (
 | 
						|
                                Body,
 | 
						|
                                Message->Header.len,
 | 
						|
                                &Message->u.Watch.VectorSize
 | 
						|
                                );
 | 
						|
 | 
						|
    EfiAcquireLock (&xs.RegisteredWatchesLock);
 | 
						|
    Message->u.Watch.Handle =
 | 
						|
      XenStoreFindWatch (Message->u.Watch.Vector[XS_WATCH_TOKEN]);
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_INFO,
 | 
						|
      "XenStore: Watch event %a\n",
 | 
						|
      Message->u.Watch.Vector[XS_WATCH_TOKEN]
 | 
						|
      ));
 | 
						|
    if (Message->u.Watch.Handle != NULL) {
 | 
						|
      EfiAcquireLock (&xs.WatchEventsLock);
 | 
						|
      InsertHeadList (&xs.WatchEvents, &Message->Link);
 | 
						|
      EfiReleaseLock (&xs.WatchEventsLock);
 | 
						|
    } else {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_WARN,
 | 
						|
        "XenStore: Watch handle %a not found\n",
 | 
						|
        Message->u.Watch.Vector[XS_WATCH_TOKEN]
 | 
						|
        ));
 | 
						|
      FreePool ((VOID *)Message->u.Watch.Vector);
 | 
						|
      FreePool (Message);
 | 
						|
    }
 | 
						|
 | 
						|
    EfiReleaseLock (&xs.RegisteredWatchesLock);
 | 
						|
  } else {
 | 
						|
    Message->u.Reply.Body = Body;
 | 
						|
    EfiAcquireLock (&xs.ReplyLock);
 | 
						|
    InsertTailList (&xs.ReplyList, &Message->Link);
 | 
						|
    EfiReleaseLock (&xs.ReplyLock);
 | 
						|
  }
 | 
						|
 | 
						|
  return XENSTORE_STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// XenStore Message Request/Reply Processing
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Convert a XenStore error string into an errno number.
 | 
						|
 | 
						|
  Unknown error strings are converted to EINVAL.
 | 
						|
 | 
						|
  @param errorstring  The error string to convert.
 | 
						|
 | 
						|
  @return  The errno best matching the input string.
 | 
						|
 | 
						|
**/
 | 
						|
typedef struct {
 | 
						|
  XENSTORE_STATUS    Status;
 | 
						|
  CONST CHAR8        *ErrorStr;
 | 
						|
} XenStoreErrors;
 | 
						|
 | 
						|
static XenStoreErrors  gXenStoreErrors[] = {
 | 
						|
  { XENSTORE_STATUS_EINVAL,    "EINVAL"    },
 | 
						|
  { XENSTORE_STATUS_EACCES,    "EACCES"    },
 | 
						|
  { XENSTORE_STATUS_EEXIST,    "EEXIST"    },
 | 
						|
  { XENSTORE_STATUS_EISDIR,    "EISDIR"    },
 | 
						|
  { XENSTORE_STATUS_ENOENT,    "ENOENT"    },
 | 
						|
  { XENSTORE_STATUS_ENOMEM,    "ENOMEM"    },
 | 
						|
  { XENSTORE_STATUS_ENOSPC,    "ENOSPC"    },
 | 
						|
  { XENSTORE_STATUS_EIO,       "EIO"       },
 | 
						|
  { XENSTORE_STATUS_ENOTEMPTY, "ENOTEMPTY" },
 | 
						|
  { XENSTORE_STATUS_ENOSYS,    "ENOSYS"    },
 | 
						|
  { XENSTORE_STATUS_EROFS,     "EROFS"     },
 | 
						|
  { XENSTORE_STATUS_EBUSY,     "EBUSY"     },
 | 
						|
  { XENSTORE_STATUS_EAGAIN,    "EAGAIN"    },
 | 
						|
  { XENSTORE_STATUS_EISCONN,   "EISCONN"   },
 | 
						|
  { XENSTORE_STATUS_E2BIG,     "E2BIG"     }
 | 
						|
};
 | 
						|
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreGetError (
 | 
						|
  CONST CHAR8  *ErrorStr
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINT32  Index;
 | 
						|
 | 
						|
  for (Index = 0; Index < ARRAY_SIZE (gXenStoreErrors); Index++) {
 | 
						|
    if (!AsciiStrCmp (ErrorStr, gXenStoreErrors[Index].ErrorStr)) {
 | 
						|
      return gXenStoreErrors[Index].Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_WARN, "XenStore gave unknown error %a\n", ErrorStr));
 | 
						|
  return XENSTORE_STATUS_EINVAL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Block waiting for a reply to a message request.
 | 
						|
 | 
						|
  @param TypePtr The returned type of the reply.
 | 
						|
  @param LenPtr  The returned body length of the reply.
 | 
						|
  @param Result  The returned body of the reply.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreReadReply (
 | 
						|
  OUT enum xsd_sockmsg_type  *TypePtr,
 | 
						|
  OUT UINT32                 *LenPtr OPTIONAL,
 | 
						|
  OUT VOID                   **Result
 | 
						|
  )
 | 
						|
{
 | 
						|
  XENSTORE_MESSAGE  *Message;
 | 
						|
  LIST_ENTRY        *Entry;
 | 
						|
  CHAR8             *Body;
 | 
						|
 | 
						|
  while (IsListEmpty (&xs.ReplyList)) {
 | 
						|
    XENSTORE_STATUS  Status;
 | 
						|
    Status = XenStoreProcessMessage ();
 | 
						|
    if ((Status != XENSTORE_STATUS_SUCCESS) && (Status != XENSTORE_STATUS_EAGAIN)) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_ERROR,
 | 
						|
        "XenStore, error while reading the ring (%d).",
 | 
						|
        Status
 | 
						|
        ));
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EfiAcquireLock (&xs.ReplyLock);
 | 
						|
  Entry   = GetFirstNode (&xs.ReplyList);
 | 
						|
  Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
 | 
						|
  RemoveEntryList (Entry);
 | 
						|
  EfiReleaseLock (&xs.ReplyLock);
 | 
						|
 | 
						|
  *TypePtr = Message->Header.type;
 | 
						|
  if (LenPtr != NULL) {
 | 
						|
    *LenPtr = Message->Header.len;
 | 
						|
  }
 | 
						|
 | 
						|
  Body = Message->u.Reply.Body;
 | 
						|
 | 
						|
  FreePool (Message);
 | 
						|
  *Result = Body;
 | 
						|
  return XENSTORE_STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Send a message with an optionally multi-part body to the XenStore service.
 | 
						|
 | 
						|
  @param Transaction    The transaction to use for this request.
 | 
						|
  @param RequestType    The type of message to send.
 | 
						|
  @param WriteRequest   Pointers to the body sections of the request.
 | 
						|
  @param NumRequests    The number of body sections in the request.
 | 
						|
  @param LenPtr         The returned length of the reply.
 | 
						|
  @param ResultPtr      The returned body of the reply.
 | 
						|
 | 
						|
  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
 | 
						|
           the cause of failure.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreTalkv (
 | 
						|
  IN  CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN  enum xsd_sockmsg_type       RequestType,
 | 
						|
  IN  CONST WRITE_REQUEST         *WriteRequest,
 | 
						|
  IN  UINT32                      NumRequests,
 | 
						|
  OUT UINT32                      *LenPtr OPTIONAL,
 | 
						|
  OUT VOID                        **ResultPtr OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  struct xsd_sockmsg  Message;
 | 
						|
  void                *Return = NULL;
 | 
						|
  UINT32              Index;
 | 
						|
  XENSTORE_STATUS     Status;
 | 
						|
 | 
						|
  if (Transaction == XST_NIL) {
 | 
						|
    Message.tx_id = 0;
 | 
						|
  } else {
 | 
						|
    Message.tx_id = Transaction->Id;
 | 
						|
  }
 | 
						|
 | 
						|
  Message.req_id = 0;
 | 
						|
  Message.type   = RequestType;
 | 
						|
  Message.len    = 0;
 | 
						|
  for (Index = 0; Index < NumRequests; Index++) {
 | 
						|
    Message.len += WriteRequest[Index].Len;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = XenStoreWriteStore (&Message, sizeof (Message));
 | 
						|
  if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "XenStoreTalkv failed %d\n", Status));
 | 
						|
    goto Error;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < NumRequests; Index++) {
 | 
						|
    Status = XenStoreWriteStore (WriteRequest[Index].Data, WriteRequest[Index].Len);
 | 
						|
    if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "XenStoreTalkv failed %d\n", Status));
 | 
						|
      goto Error;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  Status = XenStoreReadReply ((enum xsd_sockmsg_type *)&Message.type, LenPtr, &Return);
 | 
						|
 | 
						|
Error:
 | 
						|
  if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Message.type == XS_ERROR) {
 | 
						|
    Status = XenStoreGetError (Return);
 | 
						|
    FreePool (Return);
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  /* Reply is either error or an echo of our request message type. */
 | 
						|
  ASSERT ((enum xsd_sockmsg_type)Message.type == RequestType);
 | 
						|
 | 
						|
  if (ResultPtr) {
 | 
						|
    *ResultPtr = Return;
 | 
						|
  } else {
 | 
						|
    FreePool (Return);
 | 
						|
  }
 | 
						|
 | 
						|
  return XENSTORE_STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Wrapper for XenStoreTalkv allowing easy transmission of a message with
 | 
						|
  a single, contiguous, message body.
 | 
						|
 | 
						|
  The returned result is provided in malloced storage and thus must be free'd
 | 
						|
  by the caller.
 | 
						|
 | 
						|
  @param Transaction    The transaction to use for this request.
 | 
						|
  @param RequestType    The type of message to send.
 | 
						|
  @param Body           The body of the request.
 | 
						|
  @param LenPtr         The returned length of the reply.
 | 
						|
  @param Result         The returned body of the reply.
 | 
						|
 | 
						|
  @return  0 on success.  Otherwise an errno indicating
 | 
						|
           the cause of failure.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreSingle (
 | 
						|
  IN  CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN  enum xsd_sockmsg_type       RequestType,
 | 
						|
  IN  CONST CHAR8                 *Body,
 | 
						|
  OUT UINT32                      *LenPtr OPTIONAL,
 | 
						|
  OUT VOID                        **Result OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  WRITE_REQUEST  WriteRequest;
 | 
						|
 | 
						|
  WriteRequest.Data = (VOID *)Body;
 | 
						|
  WriteRequest.Len  = (UINT32)AsciiStrSize (Body);
 | 
						|
 | 
						|
  return XenStoreTalkv (
 | 
						|
           Transaction,
 | 
						|
           RequestType,
 | 
						|
           &WriteRequest,
 | 
						|
           1,
 | 
						|
           LenPtr,
 | 
						|
           Result
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// XenStore Watch Support
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Transmit a watch request to the XenStore service.
 | 
						|
 | 
						|
  @param Path    The path in the XenStore to watch.
 | 
						|
  @param Tocken  A unique identifier for this watch.
 | 
						|
 | 
						|
  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating the
 | 
						|
           cause of failure.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreWatch (
 | 
						|
  CONST CHAR8  *Path,
 | 
						|
  CONST CHAR8  *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  WRITE_REQUEST  WriteRequest[2];
 | 
						|
 | 
						|
  WriteRequest[0].Data = (VOID *)Path;
 | 
						|
  WriteRequest[0].Len  = (UINT32)AsciiStrSize (Path);
 | 
						|
  WriteRequest[1].Data = (VOID *)Token;
 | 
						|
  WriteRequest[1].Len  = (UINT32)AsciiStrSize (Token);
 | 
						|
 | 
						|
  return XenStoreTalkv (XST_NIL, XS_WATCH, WriteRequest, 2, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Transmit an uwatch request to the XenStore service.
 | 
						|
 | 
						|
  @param Path    The path in the XenStore to watch.
 | 
						|
  @param Tocken  A unique identifier for this watch.
 | 
						|
 | 
						|
  @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
 | 
						|
           the cause of failure.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreUnwatch (
 | 
						|
  CONST CHAR8  *Path,
 | 
						|
  CONST CHAR8  *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  WRITE_REQUEST  WriteRequest[2];
 | 
						|
 | 
						|
  WriteRequest[0].Data = (VOID *)Path;
 | 
						|
  WriteRequest[0].Len  = (UINT32)AsciiStrSize (Path);
 | 
						|
  WriteRequest[1].Data = (VOID *)Token;
 | 
						|
  WriteRequest[1].Len  = (UINT32)AsciiStrSize (Token);
 | 
						|
 | 
						|
  return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
STATIC
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreWaitWatch (
 | 
						|
  VOID  *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  XENSTORE_MESSAGE  *Message;
 | 
						|
  LIST_ENTRY        *Entry = NULL;
 | 
						|
  LIST_ENTRY        *Last  = NULL;
 | 
						|
  XENSTORE_STATUS   Status;
 | 
						|
 | 
						|
  while (TRUE) {
 | 
						|
    EfiAcquireLock (&xs.WatchEventsLock);
 | 
						|
    if (IsListEmpty (&xs.WatchEvents) ||
 | 
						|
        (Last == GetFirstNode (&xs.WatchEvents)))
 | 
						|
    {
 | 
						|
      EfiReleaseLock (&xs.WatchEventsLock);
 | 
						|
      Status = XenStoreProcessMessage ();
 | 
						|
      if ((Status != XENSTORE_STATUS_SUCCESS) && (Status != XENSTORE_STATUS_EAGAIN)) {
 | 
						|
        return Status;
 | 
						|
      }
 | 
						|
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    for (Entry = GetFirstNode (&xs.WatchEvents);
 | 
						|
         Entry != Last && !IsNull (&xs.WatchEvents, Entry);
 | 
						|
         Entry = GetNextNode (&xs.WatchEvents, Entry))
 | 
						|
    {
 | 
						|
      Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
 | 
						|
      if (Message->u.Watch.Handle == Token) {
 | 
						|
        RemoveEntryList (Entry);
 | 
						|
        EfiReleaseLock (&xs.WatchEventsLock);
 | 
						|
        FreePool ((VOID *)Message->u.Watch.Vector);
 | 
						|
        FreePool (Message);
 | 
						|
        return XENSTORE_STATUS_SUCCESS;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Last = GetFirstNode (&xs.WatchEvents);
 | 
						|
    EfiReleaseLock (&xs.WatchEventsLock);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
NotifyEventChannelCheckForEvent (
 | 
						|
  IN EFI_EVENT  Event,
 | 
						|
  IN VOID       *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  XENSTORE_PRIVATE  *xsp;
 | 
						|
 | 
						|
  xsp = (XENSTORE_PRIVATE *)Context;
 | 
						|
  if (TestAndClearBit (xsp->EventChannel, xsp->Dev->SharedInfo->evtchn_pending)) {
 | 
						|
    gBS->SignalEvent (Event);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Setup communication channels with the XenStore service.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS if everything went well.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
XenStoreInitComms (
 | 
						|
  XENSTORE_PRIVATE  *xsp
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_EVENT                         TimerEvent;
 | 
						|
  struct xenstore_domain_interface  *XenStore = xsp->XenStore;
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
 | 
						|
  Status = gBS->SetTimer (
 | 
						|
                  TimerEvent,
 | 
						|
                  TimerRelative,
 | 
						|
                  EFI_TIMER_PERIOD_SECONDS (5)
 | 
						|
                  );
 | 
						|
  while (XenStore->rsp_prod != XenStore->rsp_cons) {
 | 
						|
    Status = gBS->CheckEvent (TimerEvent);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_WARN,
 | 
						|
        "XENSTORE response ring is not quiescent "
 | 
						|
        "(%08x:%08x): fixing up\n",
 | 
						|
        XenStore->rsp_cons,
 | 
						|
        XenStore->rsp_prod
 | 
						|
        ));
 | 
						|
      XenStore->rsp_cons = XenStore->rsp_prod;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->CloseEvent (TimerEvent);
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_WAIT,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  NotifyEventChannelCheckForEvent,
 | 
						|
                  xsp,
 | 
						|
                  &xsp->EventChannelEvent
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize XenStore.
 | 
						|
 | 
						|
  @param Dev  A XENBUS_DEVICE instance.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS if everything went well.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
XenStoreInit (
 | 
						|
  XENBUS_DEVICE  *Dev
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The HVM guest pseudo-physical frame number.  This is Xen's mapping
 | 
						|
   * of the true machine frame number into our "physical address space".
 | 
						|
   */
 | 
						|
  UINTN  XenStoreGpfn;
 | 
						|
 | 
						|
  xs.Dev = Dev;
 | 
						|
 | 
						|
  xs.EventChannel = (evtchn_port_t)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN);
 | 
						|
  XenStoreGpfn    = (UINTN)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN);
 | 
						|
  xs.XenStore     = (VOID *)(XenStoreGpfn << EFI_PAGE_SHIFT);
 | 
						|
  DEBUG ((
 | 
						|
    DEBUG_INFO,
 | 
						|
    "XenBusInit: XenBus rings @%p, event channel %x\n",
 | 
						|
    xs.XenStore,
 | 
						|
    xs.EventChannel
 | 
						|
    ));
 | 
						|
 | 
						|
  InitializeListHead (&xs.ReplyList);
 | 
						|
  InitializeListHead (&xs.WatchEvents);
 | 
						|
  InitializeListHead (&xs.RegisteredWatches);
 | 
						|
 | 
						|
  EfiInitializeLock (&xs.ReplyLock, TPL_NOTIFY);
 | 
						|
  EfiInitializeLock (&xs.RegisteredWatchesLock, TPL_NOTIFY);
 | 
						|
  EfiInitializeLock (&xs.WatchEventsLock, TPL_NOTIFY);
 | 
						|
 | 
						|
  /* Initialize the shared memory rings to talk to xenstored */
 | 
						|
  Status = XenStoreInitComms (&xs);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
XenStoreDeinit (
 | 
						|
  IN XENBUS_DEVICE  *Dev
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // Emptying the list RegisteredWatches, but this list should already be
 | 
						|
  // empty. Every driver that is using Watches should unregister them when
 | 
						|
  // it is stopped.
 | 
						|
  //
 | 
						|
  if (!IsListEmpty (&xs.RegisteredWatches)) {
 | 
						|
    XENSTORE_WATCH  *Watch;
 | 
						|
    LIST_ENTRY      *Entry;
 | 
						|
    DEBUG ((DEBUG_WARN, "XenStore: RegisteredWatches is not empty, cleaning up..."));
 | 
						|
    Entry = GetFirstNode (&xs.RegisteredWatches);
 | 
						|
    while (!IsNull (&xs.RegisteredWatches, Entry)) {
 | 
						|
      Watch = XENSTORE_WATCH_FROM_LINK (Entry);
 | 
						|
      Entry = GetNextNode (&xs.RegisteredWatches, Entry);
 | 
						|
 | 
						|
      XenStoreUnregisterWatch (Watch);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Emptying the list WatchEvents, but this list should already be empty after
 | 
						|
  // having cleanup the list RegisteredWatches.
 | 
						|
  //
 | 
						|
  if (!IsListEmpty (&xs.WatchEvents)) {
 | 
						|
    LIST_ENTRY  *Entry;
 | 
						|
    DEBUG ((DEBUG_WARN, "XenStore: WatchEvents is not empty, cleaning up..."));
 | 
						|
    Entry = GetFirstNode (&xs.WatchEvents);
 | 
						|
    while (!IsNull (&xs.WatchEvents, Entry)) {
 | 
						|
      XENSTORE_MESSAGE  *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
 | 
						|
      Entry = GetNextNode (&xs.WatchEvents, Entry);
 | 
						|
      RemoveEntryList (&Message->Link);
 | 
						|
      FreePool ((VOID *)Message->u.Watch.Vector);
 | 
						|
      FreePool (Message);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (!IsListEmpty (&xs.ReplyList)) {
 | 
						|
    XENSTORE_MESSAGE  *Message;
 | 
						|
    LIST_ENTRY        *Entry;
 | 
						|
    Entry = GetFirstNode (&xs.ReplyList);
 | 
						|
    while (!IsNull (&xs.ReplyList, Entry)) {
 | 
						|
      Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
 | 
						|
      Entry   = GetNextNode (&xs.ReplyList, Entry);
 | 
						|
      RemoveEntryList (&Message->Link);
 | 
						|
      FreePool (Message->u.Reply.Body);
 | 
						|
      FreePool (Message);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->CloseEvent (xs.EventChannelEvent);
 | 
						|
 | 
						|
  if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) {
 | 
						|
    xs.XenStore->connection = XENSTORE_RECONNECT;
 | 
						|
    XenEventChannelNotify (xs.Dev, xs.EventChannel);
 | 
						|
    while (*(volatile UINT32 *)&xs.XenStore->connection == XENSTORE_RECONNECT) {
 | 
						|
      XenStoreWaitForEvent (xs.EventChannelEvent, EFI_TIMER_PERIOD_MILLISECONDS (100));
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    /* If the backend reads the state while we're erasing it then the
 | 
						|
     * ring state will become corrupted, preventing guest frontends from
 | 
						|
     * connecting. This is rare. To help diagnose the failure, we fill
 | 
						|
     * the ring with XS_INVALID packets. */
 | 
						|
    SetMem (xs.XenStore->req, XENSTORE_RING_SIZE, 0xff);
 | 
						|
    SetMem (xs.XenStore->rsp, XENSTORE_RING_SIZE, 0xff);
 | 
						|
    xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
 | 
						|
    xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  xs.XenStore = NULL;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Public API
 | 
						|
// API comments for these methods can be found in XenStore.h
 | 
						|
//
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreListDirectory (
 | 
						|
  IN  CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN  CONST CHAR8                 *DirectoryPath,
 | 
						|
  IN  CONST CHAR8                 *Node,
 | 
						|
  OUT UINT32                      *DirectoryCountPtr,
 | 
						|
  OUT CONST CHAR8                 ***DirectoryListPtr
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8            *Path;
 | 
						|
  CHAR8            *TempStr;
 | 
						|
  UINT32           Len = 0;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
 | 
						|
  Path   = XenStoreJoin (DirectoryPath, Node);
 | 
						|
  Status = XenStoreSingle (
 | 
						|
             Transaction,
 | 
						|
             XS_DIRECTORY,
 | 
						|
             Path,
 | 
						|
             &Len,
 | 
						|
             (VOID **)&TempStr
 | 
						|
             );
 | 
						|
  FreePool (Path);
 | 
						|
  if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  *DirectoryListPtr = Split (TempStr, Len, DirectoryCountPtr);
 | 
						|
 | 
						|
  return XENSTORE_STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
XenStorePathExists (
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN CONST CHAR8                 *Directory,
 | 
						|
  IN CONST CHAR8                 *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  CONST CHAR8      **TempStr;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
  UINT32           TempNum;
 | 
						|
 | 
						|
  Status = XenStoreListDirectory (
 | 
						|
             Transaction,
 | 
						|
             Directory,
 | 
						|
             Node,
 | 
						|
             &TempNum,
 | 
						|
             &TempStr
 | 
						|
             );
 | 
						|
  if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool ((VOID *)TempStr);
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreRead (
 | 
						|
  IN  CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN  CONST CHAR8                 *DirectoryPath,
 | 
						|
  IN  CONST CHAR8                 *Node,
 | 
						|
  OUT UINT32                      *LenPtr OPTIONAL,
 | 
						|
  OUT VOID                        **Result
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8            *Path;
 | 
						|
  VOID             *Value;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
 | 
						|
  Path   = XenStoreJoin (DirectoryPath, Node);
 | 
						|
  Status = XenStoreSingle (Transaction, XS_READ, Path, LenPtr, &Value);
 | 
						|
  FreePool (Path);
 | 
						|
  if (Status != XENSTORE_STATUS_SUCCESS) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  *Result = Value;
 | 
						|
  return XENSTORE_STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreWrite (
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN CONST CHAR8                 *DirectoryPath,
 | 
						|
  IN CONST CHAR8                 *Node,
 | 
						|
  IN CONST CHAR8                 *Str
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8            *Path;
 | 
						|
  WRITE_REQUEST    WriteRequest[2];
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
 | 
						|
  Path = XenStoreJoin (DirectoryPath, Node);
 | 
						|
 | 
						|
  WriteRequest[0].Data = (VOID *)Path;
 | 
						|
  WriteRequest[0].Len  = (UINT32)AsciiStrSize (Path);
 | 
						|
  WriteRequest[1].Data = (VOID *)Str;
 | 
						|
  WriteRequest[1].Len  = (UINT32)AsciiStrLen (Str);
 | 
						|
 | 
						|
  Status = XenStoreTalkv (Transaction, XS_WRITE, WriteRequest, 2, NULL, NULL);
 | 
						|
  FreePool (Path);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreRemove (
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN CONST CHAR8                 *DirectoryPath,
 | 
						|
  IN CONST CHAR8                 *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8            *Path;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
 | 
						|
  Path   = XenStoreJoin (DirectoryPath, Node);
 | 
						|
  Status = XenStoreSingle (Transaction, XS_RM, Path, NULL, NULL);
 | 
						|
  FreePool (Path);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreTransactionStart (
 | 
						|
  OUT XENSTORE_TRANSACTION  *Transaction
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8            *IdStr;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
 | 
						|
  Status = XenStoreSingle (
 | 
						|
             XST_NIL,
 | 
						|
             XS_TRANSACTION_START,
 | 
						|
             "",
 | 
						|
             NULL,
 | 
						|
             (VOID **)&IdStr
 | 
						|
             );
 | 
						|
  if (Status == XENSTORE_STATUS_SUCCESS) {
 | 
						|
    Transaction->Id = (UINT32)AsciiStrDecimalToUintn (IdStr);
 | 
						|
    FreePool (IdStr);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreTransactionEnd (
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN BOOLEAN                     Abort
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8  AbortStr[2];
 | 
						|
 | 
						|
  AbortStr[0] = Abort ? 'F' : 'T';
 | 
						|
  AbortStr[1] = '\0';
 | 
						|
 | 
						|
  return XenStoreSingle (Transaction, XS_TRANSACTION_END, AbortStr, NULL, NULL);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenStoreVSPrint (
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN CONST CHAR8                 *DirectoryPath,
 | 
						|
  IN CONST CHAR8                 *Node,
 | 
						|
  IN CONST CHAR8                 *FormatString,
 | 
						|
  IN VA_LIST                     Marker
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8            *Buf;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
  UINTN            BufSize;
 | 
						|
  VA_LIST          Marker2;
 | 
						|
 | 
						|
  VA_COPY (Marker2, Marker);
 | 
						|
  BufSize = SPrintLengthAsciiFormat (FormatString, Marker2) + 1;
 | 
						|
  VA_END (Marker2);
 | 
						|
  Buf = AllocateZeroPool (BufSize);
 | 
						|
  AsciiVSPrint (Buf, BufSize, FormatString, Marker);
 | 
						|
  Status = XenStoreWrite (Transaction, DirectoryPath, Node, Buf);
 | 
						|
  FreePool (Buf);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenStoreSPrint (
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN CONST CHAR8                 *DirectoryPath,
 | 
						|
  IN CONST CHAR8                 *Node,
 | 
						|
  IN CONST CHAR8                 *FormatString,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  VA_LIST          Marker;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
 | 
						|
  VA_START (Marker, FormatString);
 | 
						|
  Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
 | 
						|
  VA_END (Marker);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
XenStoreRegisterWatch (
 | 
						|
  IN CONST CHAR8      *DirectoryPath,
 | 
						|
  IN CONST CHAR8      *Node,
 | 
						|
  OUT XENSTORE_WATCH  **WatchPtr
 | 
						|
  )
 | 
						|
{
 | 
						|
  /* Pointer in ascii is the token. */
 | 
						|
  CHAR8            Token[sizeof (XENSTORE_WATCH) * 2 + 1];
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
  XENSTORE_WATCH   *Watch;
 | 
						|
 | 
						|
  Watch            = AllocateZeroPool (sizeof (XENSTORE_WATCH));
 | 
						|
  Watch->Signature = XENSTORE_WATCH_SIGNATURE;
 | 
						|
  Watch->Node      = XenStoreJoin (DirectoryPath, Node);
 | 
						|
 | 
						|
  EfiAcquireLock (&xs.RegisteredWatchesLock);
 | 
						|
  InsertTailList (&xs.RegisteredWatches, &Watch->Link);
 | 
						|
  EfiReleaseLock (&xs.RegisteredWatchesLock);
 | 
						|
 | 
						|
  AsciiSPrint (Token, sizeof (Token), "%p", (VOID *)Watch);
 | 
						|
  Status = XenStoreWatch (Watch->Node, Token);
 | 
						|
 | 
						|
  /* Ignore errors due to multiple registration. */
 | 
						|
  if (Status == XENSTORE_STATUS_EEXIST) {
 | 
						|
    Status = XENSTORE_STATUS_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Status == XENSTORE_STATUS_SUCCESS) {
 | 
						|
    *WatchPtr = Watch;
 | 
						|
  } else {
 | 
						|
    EfiAcquireLock (&xs.RegisteredWatchesLock);
 | 
						|
    RemoveEntryList (&Watch->Link);
 | 
						|
    EfiReleaseLock (&xs.RegisteredWatchesLock);
 | 
						|
    FreePool (Watch->Node);
 | 
						|
    FreePool (Watch);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
XenStoreUnregisterWatch (
 | 
						|
  IN XENSTORE_WATCH  *Watch
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8       Token[sizeof (Watch) * 2 + 1];
 | 
						|
  LIST_ENTRY  *Entry;
 | 
						|
 | 
						|
  ASSERT (Watch->Signature == XENSTORE_WATCH_SIGNATURE);
 | 
						|
 | 
						|
  AsciiSPrint (Token, sizeof (Token), "%p", (VOID *)Watch);
 | 
						|
  if (XenStoreFindWatch (Token) == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  EfiAcquireLock (&xs.RegisteredWatchesLock);
 | 
						|
  RemoveEntryList (&Watch->Link);
 | 
						|
  EfiReleaseLock (&xs.RegisteredWatchesLock);
 | 
						|
 | 
						|
  XenStoreUnwatch (Watch->Node, Token);
 | 
						|
 | 
						|
  /* Cancel pending watch events. */
 | 
						|
  EfiAcquireLock (&xs.WatchEventsLock);
 | 
						|
  Entry = GetFirstNode (&xs.WatchEvents);
 | 
						|
  while (!IsNull (&xs.WatchEvents, Entry)) {
 | 
						|
    XENSTORE_MESSAGE  *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
 | 
						|
    Entry = GetNextNode (&xs.WatchEvents, Entry);
 | 
						|
    if (Message->u.Watch.Handle == Watch) {
 | 
						|
      RemoveEntryList (&Message->Link);
 | 
						|
      FreePool ((VOID *)Message->u.Watch.Vector);
 | 
						|
      FreePool (Message);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  EfiReleaseLock (&xs.WatchEventsLock);
 | 
						|
 | 
						|
  FreePool (Watch->Node);
 | 
						|
  FreePool (Watch);
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// XENBUS protocol
 | 
						|
//
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusWaitForWatch (
 | 
						|
  IN XENBUS_PROTOCOL  *This,
 | 
						|
  IN VOID             *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreWaitWatch (Token);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusXenStoreRead (
 | 
						|
  IN  XENBUS_PROTOCOL             *This,
 | 
						|
  IN  CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN  CONST CHAR8                 *Node,
 | 
						|
  OUT VOID                        **Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreRead (Transaction, This->Node, Node, NULL, Value);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusXenStoreBackendRead (
 | 
						|
  IN  XENBUS_PROTOCOL             *This,
 | 
						|
  IN  CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN  CONST CHAR8                 *Node,
 | 
						|
  OUT VOID                        **Value
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreRead (Transaction, This->Backend, Node, NULL, Value);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusXenStoreRemove (
 | 
						|
  IN XENBUS_PROTOCOL             *This,
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN const char                  *Node
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreRemove (Transaction, This->Node, Node);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusXenStoreTransactionStart (
 | 
						|
  IN  XENBUS_PROTOCOL       *This,
 | 
						|
  OUT XENSTORE_TRANSACTION  *Transaction
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreTransactionStart (Transaction);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusXenStoreTransactionEnd (
 | 
						|
  IN XENBUS_PROTOCOL             *This,
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN BOOLEAN                     Abort
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreTransactionEnd (Transaction, Abort);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusXenStoreSPrint (
 | 
						|
  IN XENBUS_PROTOCOL             *This,
 | 
						|
  IN CONST XENSTORE_TRANSACTION  *Transaction,
 | 
						|
  IN CONST CHAR8                 *DirectoryPath,
 | 
						|
  IN CONST CHAR8                 *Node,
 | 
						|
  IN CONST CHAR8                 *FormatString,
 | 
						|
  ...
 | 
						|
  )
 | 
						|
{
 | 
						|
  VA_LIST          Marker;
 | 
						|
  XENSTORE_STATUS  Status;
 | 
						|
 | 
						|
  VA_START (Marker, FormatString);
 | 
						|
  Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
 | 
						|
  VA_END (Marker);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusRegisterWatch (
 | 
						|
  IN  XENBUS_PROTOCOL  *This,
 | 
						|
  IN  CONST CHAR8      *Node,
 | 
						|
  OUT VOID             **Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreRegisterWatch (This->Node, Node, (XENSTORE_WATCH **)Token);
 | 
						|
}
 | 
						|
 | 
						|
XENSTORE_STATUS
 | 
						|
EFIAPI
 | 
						|
XenBusRegisterWatchBackend (
 | 
						|
  IN  XENBUS_PROTOCOL  *This,
 | 
						|
  IN  CONST CHAR8      *Node,
 | 
						|
  OUT VOID             **Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  return XenStoreRegisterWatch (This->Backend, Node, (XENSTORE_WATCH **)Token);
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
XenBusUnregisterWatch (
 | 
						|
  IN XENBUS_PROTOCOL  *This,
 | 
						|
  IN VOID             *Token
 | 
						|
  )
 | 
						|
{
 | 
						|
  XenStoreUnregisterWatch ((XENSTORE_WATCH *)Token);
 | 
						|
}
 |