Home | History | Annotate | Download | only in XenBusDxe
      1 /** @file
      2   Low-level kernel interface to the XenStore.
      3 
      4   The XenStore interface is a simple storage system that is a means of
      5   communicating state and configuration data between the Xen Domain 0
      6   and the various guest domains.  All configuration data other than
      7   a small amount of essential information required during the early
      8   boot process of launching a Xen aware guest, is managed using the
      9   XenStore.
     10 
     11   The XenStore is ASCII string based, and has a structure and semantics
     12   similar to a filesystem.  There are files and directories, the directories
     13   able to contain files or other directories.  The depth of the hierachy
     14   is only limited by the XenStore's maximum path length.
     15 
     16   The communication channel between the XenStore service and other
     17   domains is via two, guest specific, ring buffers in a shared memory
     18   area.  One ring buffer is used for communicating in each direction.
     19   The grant table references for this shared memory are given to the
     20   guest either via the xen_start_info structure for a fully para-
     21   virtualized guest, or via HVM hypercalls for a hardware virtualized
     22   guest.
     23 
     24   The XenStore communication relies on an event channel and thus
     25   interrupts.  But under OVMF this XenStore client will pull the
     26   state of the event channel.
     27 
     28   Several Xen services depend on the XenStore, most notably the
     29   XenBus used to discover and manage Xen devices.
     30 
     31   Copyright (C) 2005 Rusty Russell, IBM Corporation
     32   Copyright (C) 2009,2010 Spectra Logic Corporation
     33   Copyright (C) 2014, Citrix Ltd.
     34 
     35   This file may be distributed separately from the Linux kernel, or
     36   incorporated into other software packages, subject to the following license:
     37 
     38   Permission is hereby granted, free of charge, to any person obtaining a copy
     39   of this source file (the "Software"), to deal in the Software without
     40   restriction, including without limitation the rights to use, copy, modify,
     41   merge, publish, distribute, sublicense, and/or sell copies of the Software,
     42   and to permit persons to whom the Software is furnished to do so, subject to
     43   the following conditions:
     44 
     45   The above copyright notice and this permission notice shall be included in
     46   all copies or substantial portions of the Software.
     47 
     48   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     49   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     50   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     51   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     52   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     53   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     54   IN THE SOFTWARE.
     55 **/
     56 
     57 #include "XenStore.h"
     58 
     59 #include <Library/PrintLib.h>
     60 
     61 #include <IndustryStandard/Xen/hvm/params.h>
     62 
     63 #include "EventChannel.h"
     64 #include <Library/XenHypercallLib.h>
     65 
     66 //
     67 // Private Data Structures
     68 //
     69 
     70 typedef struct {
     71   CONST VOID  *Data;
     72   UINT32      Len;
     73 } WRITE_REQUEST;
     74 
     75 /* Register callback to watch subtree (node) in the XenStore. */
     76 #define XENSTORE_WATCH_SIGNATURE SIGNATURE_32 ('X','S','w','a')
     77 struct _XENSTORE_WATCH
     78 {
     79   UINT32      Signature;
     80   LIST_ENTRY  Link;
     81 
     82   /* Path being watched. */
     83   CHAR8       *Node;
     84 };
     85 
     86 #define XENSTORE_WATCH_FROM_LINK(l) \
     87   CR (l, XENSTORE_WATCH, Link, XENSTORE_WATCH_SIGNATURE)
     88 
     89 
     90 /**
     91  * Structure capturing messages received from the XenStore service.
     92  */
     93 #define XENSTORE_MESSAGE_SIGNATURE SIGNATURE_32 ('X', 'S', 's', 'm')
     94 typedef struct {
     95   UINT32 Signature;
     96   LIST_ENTRY Link;
     97 
     98   struct xsd_sockmsg Header;
     99 
    100   union {
    101     /* Queued replies. */
    102     struct {
    103       CHAR8 *Body;
    104     } Reply;
    105 
    106     /* Queued watch events. */
    107     struct {
    108       XENSTORE_WATCH *Handle;
    109       CONST CHAR8 **Vector;
    110       UINT32 VectorSize;
    111     } Watch;
    112   } u;
    113 } XENSTORE_MESSAGE;
    114 #define XENSTORE_MESSAGE_FROM_LINK(r) \
    115   CR (r, XENSTORE_MESSAGE, Link, XENSTORE_MESSAGE_SIGNATURE)
    116 
    117 /**
    118  * Container for all XenStore related state.
    119  */
    120 typedef struct {
    121   /**
    122    * Pointer to shared memory communication structures allowing us
    123    * to communicate with the XenStore service.
    124    */
    125   struct xenstore_domain_interface *XenStore;
    126 
    127   XENBUS_DEVICE *Dev;
    128 
    129   /**
    130    * A list of replies to our requests.
    131    *
    132    * The reply list is filled by xs_rcv_thread().  It
    133    * is consumed by the context that issued the request
    134    * to which a reply is made.  The requester blocks in
    135    * XenStoreReadReply ().
    136    *
    137    * /note Only one requesting context can be active at a time.
    138    */
    139   LIST_ENTRY ReplyList;
    140 
    141   /** Lock protecting the reply list. */
    142   EFI_LOCK ReplyLock;
    143 
    144   /**
    145    * List of registered watches.
    146    */
    147   LIST_ENTRY RegisteredWatches;
    148 
    149   /** Lock protecting the registered watches list. */
    150   EFI_LOCK RegisteredWatchesLock;
    151 
    152   /**
    153    * List of pending watch callback events.
    154    */
    155   LIST_ENTRY WatchEvents;
    156 
    157   /** Lock protecting the watch calback list. */
    158   EFI_LOCK WatchEventsLock;
    159 
    160   /**
    161    * The event channel for communicating with the
    162    * XenStore service.
    163    */
    164   evtchn_port_t EventChannel;
    165 
    166   /** Handle for XenStore events. */
    167   EFI_EVENT EventChannelEvent;
    168 } XENSTORE_PRIVATE;
    169 
    170 //
    171 // Global Data
    172 //
    173 static XENSTORE_PRIVATE xs;
    174 
    175 
    176 //
    177 // Private Utility Functions
    178 //
    179 
    180 /**
    181   Count and optionally record pointers to a number of NUL terminated
    182   strings in a buffer.
    183 
    184   @param Strings  A pointer to a contiguous buffer of NUL terminated strings.
    185   @param Len      The length of the buffer pointed to by strings.
    186   @param Dst      An array to store pointers to each string found in strings.
    187 
    188   @return  A count of the number of strings found.
    189 **/
    190 STATIC
    191 UINT32
    192 ExtractStrings (
    193   IN  CONST CHAR8 *Strings,
    194   IN  UINTN       Len,
    195   OUT CONST CHAR8 **Dst OPTIONAL
    196   )
    197 {
    198   UINT32 Num = 0;
    199   CONST CHAR8 *Ptr;
    200 
    201   for (Ptr = Strings; Ptr < Strings + Len; Ptr += AsciiStrSize (Ptr)) {
    202     if (Dst != NULL) {
    203       *Dst++ = Ptr;
    204     }
    205     Num++;
    206   }
    207 
    208   return Num;
    209 }
    210 
    211 /**
    212   Convert a contiguous buffer containing a series of NUL terminated
    213   strings into an array of pointers to strings.
    214 
    215   The returned pointer references the array of string pointers which
    216   is followed by the storage for the string data.  It is the client's
    217   responsibility to free this storage.
    218 
    219   The storage addressed by Strings is free'd prior to Split returning.
    220 
    221   @param Strings  A pointer to a contiguous buffer of NUL terminated strings.
    222   @param Len      The length of the buffer pointed to by strings.
    223   @param NumPtr   The number of strings found and returned in the strings
    224                   array.
    225 
    226   @return  An array of pointers to the strings found in the input buffer.
    227 **/
    228 STATIC
    229 CONST CHAR8 **
    230 Split (
    231   IN  CHAR8   *Strings,
    232   IN  UINTN   Len,
    233   OUT UINT32  *NumPtr
    234   )
    235 {
    236   CONST CHAR8 **Dst;
    237 
    238   ASSERT(NumPtr != NULL);
    239   ASSERT(Strings != NULL);
    240 
    241   /* Protect against unterminated buffers. */
    242   if (Len > 0) {
    243     Strings[Len - 1] = '\0';
    244   }
    245 
    246   /* Count the Strings. */
    247   *NumPtr = ExtractStrings (Strings, Len, NULL);
    248 
    249   /* Transfer to one big alloc for easy freeing by the caller. */
    250   Dst = AllocatePool (*NumPtr * sizeof (CHAR8 *) + Len);
    251   CopyMem ((VOID*)&Dst[*NumPtr], Strings, Len);
    252   FreePool (Strings);
    253 
    254   /* Extract pointers to newly allocated array. */
    255   Strings = (CHAR8 *) &Dst[*NumPtr];
    256   ExtractStrings (Strings, Len, Dst);
    257 
    258   return (Dst);
    259 }
    260 
    261 /**
    262   Convert from watch token (unique identifier) to the associated
    263   internal tracking structure for this watch.
    264 
    265   @param Tocken  The unique identifier for the watch to find.
    266 
    267   @return  A pointer to the found watch structure or NULL.
    268 **/
    269 STATIC
    270 XENSTORE_WATCH *
    271 XenStoreFindWatch (
    272   IN CONST CHAR8 *Token
    273   )
    274 {
    275   XENSTORE_WATCH *Watch, *WantedWatch;
    276   LIST_ENTRY *Entry;
    277 
    278   WantedWatch = (VOID *) AsciiStrHexToUintn (Token);
    279 
    280   if (IsListEmpty (&xs.RegisteredWatches)) {
    281     return NULL;
    282   }
    283   for (Entry = GetFirstNode (&xs.RegisteredWatches);
    284        !IsNull (&xs.RegisteredWatches, Entry);
    285        Entry = GetNextNode (&xs.RegisteredWatches, Entry)) {
    286     Watch = XENSTORE_WATCH_FROM_LINK (Entry);
    287     if (Watch == WantedWatch)
    288       return Watch;
    289   }
    290 
    291   return NULL;
    292 }
    293 
    294 //
    295 // Public Utility Functions
    296 // API comments for these methods can be found in XenStore.h
    297 //
    298 
    299 CHAR8 *
    300 XenStoreJoin (
    301   IN CONST CHAR8 *DirectoryPath,
    302   IN CONST CHAR8 *Node
    303   )
    304 {
    305   CHAR8 *Buf;
    306 
    307   /* +1 for '/' and +1 for '\0' */
    308   Buf = AllocateZeroPool (
    309           AsciiStrLen (DirectoryPath) + AsciiStrLen (Node) + 2);
    310   AsciiStrCat (Buf, DirectoryPath);
    311   if (Node[0] != '\0') {
    312     AsciiStrCat (Buf, "/");
    313     AsciiStrCat (Buf, Node);
    314   }
    315 
    316   return Buf;
    317 }
    318 
    319 //
    320 // Low Level Communication Management
    321 //
    322 
    323 /**
    324   Verify that the indexes for a ring are valid.
    325 
    326   The difference between the producer and consumer cannot
    327   exceed the size of the ring.
    328 
    329   @param Cons  The consumer index for the ring to test.
    330   @param Prod  The producer index for the ring to test.
    331 
    332   @retval TRUE   If indexes are in range.
    333   @retval FALSE  If the indexes are out of range.
    334 **/
    335 STATIC
    336 BOOLEAN
    337 XenStoreCheckIndexes (
    338   XENSTORE_RING_IDX Cons,
    339   XENSTORE_RING_IDX Prod
    340   )
    341 {
    342   return ((Prod - Cons) <= XENSTORE_RING_SIZE);
    343 }
    344 
    345 /**
    346   Return a pointer to, and the length of, the contiguous
    347   free region available for output in a ring buffer.
    348 
    349   @param Cons    The consumer index for the ring.
    350   @param Prod    The producer index for the ring.
    351   @param Buffer  The base address of the ring's storage.
    352   @param LenPtr  The amount of contiguous storage available.
    353 
    354   @return  A pointer to the start location of the free region.
    355 **/
    356 STATIC
    357 VOID *
    358 XenStoreGetOutputChunk (
    359   IN  XENSTORE_RING_IDX Cons,
    360   IN  XENSTORE_RING_IDX Prod,
    361   IN  CHAR8             *Buffer,
    362   OUT UINT32            *LenPtr
    363   )
    364 {
    365   UINT32 Len;
    366   Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Prod);
    367   if ((XENSTORE_RING_SIZE - (Prod - Cons)) < Len) {
    368     Len = XENSTORE_RING_SIZE - (Prod - Cons);
    369   }
    370   *LenPtr = Len;
    371   return (Buffer + MASK_XENSTORE_IDX (Prod));
    372 }
    373 
    374 /**
    375   Return a pointer to, and the length of, the contiguous
    376   data available to read from a ring buffer.
    377 
    378   @param Cons    The consumer index for the ring.
    379   @param Prod    The producer index for the ring.
    380   @param Buffer  The base address of the ring's storage.
    381   @param LenPtr  The amount of contiguous data available to read.
    382 
    383   @return  A pointer to the start location of the available data.
    384 **/
    385 STATIC
    386 CONST VOID *
    387 XenStoreGetInputChunk (
    388   IN  XENSTORE_RING_IDX Cons,
    389   IN  XENSTORE_RING_IDX Prod,
    390   IN  CONST CHAR8       *Buffer,
    391   OUT UINT32            *LenPtr
    392   )
    393 {
    394   UINT32 Len;
    395 
    396   Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Cons);
    397   if ((Prod - Cons) < Len) {
    398     Len = Prod - Cons;
    399   }
    400   *LenPtr = Len;
    401   return (Buffer + MASK_XENSTORE_IDX (Cons));
    402 }
    403 
    404 /**
    405   Wait for an event or timeout.
    406 
    407   @param Event    Event to wait for.
    408   @param Timeout  A timeout value in 100ns units.
    409 
    410   @retval EFI_SUCCESS   Event have been triggered or the current TPL is not
    411                         TPL_APPLICATION.
    412   @retval EFI_TIMEOUT   Timeout have expired.
    413 **/
    414 STATIC
    415 EFI_STATUS
    416 XenStoreWaitForEvent (
    417   IN EFI_EVENT Event,
    418   IN UINT64    Timeout
    419   )
    420 {
    421   UINTN Index;
    422   EFI_STATUS Status;
    423   EFI_EVENT TimerEvent;
    424   EFI_EVENT WaitList[2];
    425 
    426   gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
    427   gBS->SetTimer (TimerEvent, TimerRelative, Timeout);
    428 
    429   WaitList[0] = xs.EventChannelEvent;
    430   WaitList[1] = TimerEvent;
    431   Status = gBS->WaitForEvent (2, WaitList, &Index);
    432   ASSERT (Status != EFI_INVALID_PARAMETER);
    433   gBS->CloseEvent (TimerEvent);
    434   if (Status == EFI_UNSUPPORTED) {
    435     return EFI_SUCCESS;
    436   }
    437   if (Index == 1) {
    438     return EFI_TIMEOUT;
    439   } else {
    440     return EFI_SUCCESS;
    441   }
    442 }
    443 
    444 /**
    445   Transmit data to the XenStore service.
    446 
    447   The buffer pointed to by DataPtr is at least Len bytes in length.
    448 
    449   @param DataPtr  A pointer to the contiguous data to send.
    450   @param Len      The amount of data to send.
    451 
    452   @return  On success 0, otherwise an errno value indicating the
    453            cause of failure.
    454 **/
    455 STATIC
    456 XENSTORE_STATUS
    457 XenStoreWriteStore (
    458   IN CONST VOID *DataPtr,
    459   IN UINT32     Len
    460   )
    461 {
    462   XENSTORE_RING_IDX Cons, Prod;
    463   CONST CHAR8 *Data = (CONST CHAR8 *)DataPtr;
    464 
    465   while (Len != 0) {
    466     void *Dest;
    467     UINT32 Available;
    468 
    469     Cons = xs.XenStore->req_cons;
    470     Prod = xs.XenStore->req_prod;
    471     if ((Prod - Cons) == XENSTORE_RING_SIZE) {
    472       /*
    473        * Output ring is full. Wait for a ring event.
    474        *
    475        * Note that the events from both queues are combined, so being woken
    476        * does not guarantee that data exist in the read ring.
    477        */
    478       EFI_STATUS Status;
    479 
    480       Status = XenStoreWaitForEvent (xs.EventChannelEvent,
    481                                      EFI_TIMER_PERIOD_SECONDS (1));
    482       if (Status == EFI_TIMEOUT) {
    483         DEBUG ((EFI_D_WARN, "XenStore Write, waiting for a ring event.\n"));
    484       }
    485       continue;
    486     }
    487 
    488     /* Verify queue sanity. */
    489     if (!XenStoreCheckIndexes (Cons, Prod)) {
    490       xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
    491       return XENSTORE_STATUS_EIO;
    492     }
    493 
    494     Dest = XenStoreGetOutputChunk (Cons, Prod, xs.XenStore->req, &Available);
    495     if (Available > Len) {
    496       Available = Len;
    497     }
    498 
    499     CopyMem (Dest, Data, Available);
    500     Data += Available;
    501     Len -= Available;
    502 
    503     /*
    504      * The store to the producer index, which indicates
    505      * to the other side that new data has arrived, must
    506      * be visible only after our copy of the data into the
    507      * ring has completed.
    508      */
    509     MemoryFence ();
    510     xs.XenStore->req_prod += Available;
    511 
    512     /*
    513      * The other side will see the change to req_prod at the time of the
    514      * interrupt.
    515      */
    516     MemoryFence ();
    517     XenEventChannelNotify (xs.Dev, xs.EventChannel);
    518   }
    519 
    520   return XENSTORE_STATUS_SUCCESS;
    521 }
    522 
    523 /**
    524   Receive data from the XenStore service.
    525 
    526   The buffer pointed to by DataPtr is at least Len bytes in length.
    527 
    528   @param DataPtr  A pointer to the contiguous buffer to receive the data.
    529   @param Len      The amount of data to receive.
    530 
    531   @return  On success 0, otherwise an errno value indicating the
    532            cause of failure.
    533 **/
    534 STATIC
    535 XENSTORE_STATUS
    536 XenStoreReadStore (
    537   OUT VOID *DataPtr,
    538   IN  UINT32 Len
    539   )
    540 {
    541   XENSTORE_RING_IDX Cons, Prod;
    542   CHAR8 *Data = (CHAR8 *) DataPtr;
    543 
    544   while (Len != 0) {
    545     UINT32 Available;
    546     CONST CHAR8 *Src;
    547 
    548     Cons = xs.XenStore->rsp_cons;
    549     Prod = xs.XenStore->rsp_prod;
    550     if (Cons == Prod) {
    551       /*
    552        * Nothing to read. Wait for a ring event.
    553        *
    554        * Note that the events from both queues are combined, so being woken
    555        * does not guarantee that data exist in the read ring.
    556        */
    557       EFI_STATUS Status;
    558 
    559       Status = XenStoreWaitForEvent (xs.EventChannelEvent,
    560                                      EFI_TIMER_PERIOD_SECONDS (1));
    561       if (Status == EFI_TIMEOUT) {
    562         DEBUG ((EFI_D_WARN, "XenStore Read, waiting for a ring event.\n"));
    563       }
    564       continue;
    565     }
    566 
    567     /* Verify queue sanity. */
    568     if (!XenStoreCheckIndexes (Cons, Prod)) {
    569       xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
    570       return XENSTORE_STATUS_EIO;
    571     }
    572 
    573     Src = XenStoreGetInputChunk (Cons, Prod, xs.XenStore->rsp, &Available);
    574     if (Available > Len) {
    575       Available = Len;
    576     }
    577 
    578     /*
    579      * Insure the data we read is related to the indexes
    580      * we read above.
    581      */
    582     MemoryFence ();
    583 
    584     CopyMem (Data, Src, Available);
    585     Data += Available;
    586     Len -= Available;
    587 
    588     /*
    589      * Insure that the producer of this ring does not see
    590      * the ring space as free until after we have copied it
    591      * out.
    592      */
    593     MemoryFence ();
    594     xs.XenStore->rsp_cons += Available;
    595 
    596     /*
    597      * The producer will see the updated consumer index when the event is
    598      * delivered.
    599      */
    600     MemoryFence ();
    601     XenEventChannelNotify (xs.Dev, xs.EventChannel);
    602   }
    603 
    604   return XENSTORE_STATUS_SUCCESS;
    605 }
    606 
    607 //
    608 // Received Message Processing
    609 //
    610 
    611 /**
    612   Block reading the next message from the XenStore service and
    613   process the result.
    614 
    615   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno value
    616            indicating the type of failure encountered.
    617 **/
    618 STATIC
    619 XENSTORE_STATUS
    620 XenStoreProcessMessage (
    621   VOID
    622   )
    623 {
    624   XENSTORE_MESSAGE *Message;
    625   CHAR8 *Body;
    626   XENSTORE_STATUS Status;
    627 
    628   Message = AllocateZeroPool (sizeof (XENSTORE_MESSAGE));
    629   Message->Signature = XENSTORE_MESSAGE_SIGNATURE;
    630   Status = XenStoreReadStore (&Message->Header, sizeof (Message->Header));
    631   if (Status != XENSTORE_STATUS_SUCCESS) {
    632     FreePool (Message);
    633     DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
    634     return Status;
    635   }
    636 
    637   Body = AllocatePool (Message->Header.len + 1);
    638   Status = XenStoreReadStore (Body, Message->Header.len);
    639   if (Status != XENSTORE_STATUS_SUCCESS) {
    640     FreePool (Body);
    641     FreePool (Message);
    642     DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
    643     return Status;
    644   }
    645   Body[Message->Header.len] = '\0';
    646 
    647   if (Message->Header.type == XS_WATCH_EVENT) {
    648     Message->u.Watch.Vector = Split(Body, Message->Header.len,
    649                                     &Message->u.Watch.VectorSize);
    650 
    651     EfiAcquireLock (&xs.RegisteredWatchesLock);
    652     Message->u.Watch.Handle =
    653       XenStoreFindWatch (Message->u.Watch.Vector[XS_WATCH_TOKEN]);
    654     DEBUG ((EFI_D_INFO, "XenStore: Watch event %a\n",
    655             Message->u.Watch.Vector[XS_WATCH_TOKEN]));
    656     if (Message->u.Watch.Handle != NULL) {
    657       EfiAcquireLock (&xs.WatchEventsLock);
    658       InsertHeadList (&xs.WatchEvents, &Message->Link);
    659       EfiReleaseLock (&xs.WatchEventsLock);
    660     } else {
    661       DEBUG ((EFI_D_WARN, "XenStore: Watch handle %a not found\n",
    662               Message->u.Watch.Vector[XS_WATCH_TOKEN]));
    663       FreePool((VOID*)Message->u.Watch.Vector);
    664       FreePool(Message);
    665     }
    666     EfiReleaseLock (&xs.RegisteredWatchesLock);
    667   } else {
    668     Message->u.Reply.Body = Body;
    669     EfiAcquireLock (&xs.ReplyLock);
    670     InsertTailList (&xs.ReplyList, &Message->Link);
    671     EfiReleaseLock (&xs.ReplyLock);
    672   }
    673 
    674   return XENSTORE_STATUS_SUCCESS;
    675 }
    676 
    677 //
    678 // XenStore Message Request/Reply Processing
    679 //
    680 
    681 /**
    682   Convert a XenStore error string into an errno number.
    683 
    684   Unknown error strings are converted to EINVAL.
    685 
    686   @param errorstring  The error string to convert.
    687 
    688   @return  The errno best matching the input string.
    689 
    690 **/
    691 typedef struct {
    692   XENSTORE_STATUS Status;
    693   CONST CHAR8 *ErrorStr;
    694 } XenStoreErrors;
    695 
    696 static XenStoreErrors gXenStoreErrors[] = {
    697   { XENSTORE_STATUS_EINVAL, "EINVAL" },
    698   { XENSTORE_STATUS_EACCES, "EACCES" },
    699   { XENSTORE_STATUS_EEXIST, "EEXIST" },
    700   { XENSTORE_STATUS_EISDIR, "EISDIR" },
    701   { XENSTORE_STATUS_ENOENT, "ENOENT" },
    702   { XENSTORE_STATUS_ENOMEM, "ENOMEM" },
    703   { XENSTORE_STATUS_ENOSPC, "ENOSPC" },
    704   { XENSTORE_STATUS_EIO, "EIO" },
    705   { XENSTORE_STATUS_ENOTEMPTY, "ENOTEMPTY" },
    706   { XENSTORE_STATUS_ENOSYS, "ENOSYS" },
    707   { XENSTORE_STATUS_EROFS, "EROFS" },
    708   { XENSTORE_STATUS_EBUSY, "EBUSY" },
    709   { XENSTORE_STATUS_EAGAIN, "EAGAIN" },
    710   { XENSTORE_STATUS_EISCONN, "EISCONN" },
    711   { XENSTORE_STATUS_E2BIG, "E2BIG" }
    712 };
    713 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
    714 
    715 STATIC
    716 XENSTORE_STATUS
    717 XenStoreGetError (
    718   CONST CHAR8 *ErrorStr
    719   )
    720 {
    721   UINT32 Index;
    722 
    723   for (Index = 0; Index < ARRAY_SIZE(gXenStoreErrors); Index++) {
    724     if (!AsciiStrCmp (ErrorStr, gXenStoreErrors[Index].ErrorStr)) {
    725       return gXenStoreErrors[Index].Status;
    726     }
    727   }
    728   DEBUG ((EFI_D_WARN, "XenStore gave unknown error %a\n", ErrorStr));
    729   return XENSTORE_STATUS_EINVAL;
    730 }
    731 
    732 /**
    733   Block waiting for a reply to a message request.
    734 
    735   @param TypePtr The returned type of the reply.
    736   @param LenPtr  The returned body length of the reply.
    737   @param Result  The returned body of the reply.
    738 **/
    739 STATIC
    740 XENSTORE_STATUS
    741 XenStoreReadReply (
    742   OUT enum xsd_sockmsg_type *TypePtr,
    743   OUT UINT32 *LenPtr OPTIONAL,
    744   OUT VOID **Result
    745   )
    746 {
    747   XENSTORE_MESSAGE *Message;
    748   LIST_ENTRY *Entry;
    749   CHAR8 *Body;
    750 
    751   while (IsListEmpty (&xs.ReplyList)) {
    752     XENSTORE_STATUS Status;
    753     Status = XenStoreProcessMessage ();
    754     if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) {
    755       DEBUG ((EFI_D_ERROR, "XenStore, error while reading the ring (%d).",
    756               Status));
    757       return Status;
    758     }
    759   }
    760   EfiAcquireLock (&xs.ReplyLock);
    761   Entry = GetFirstNode (&xs.ReplyList);
    762   Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
    763   RemoveEntryList (Entry);
    764   EfiReleaseLock (&xs.ReplyLock);
    765 
    766   *TypePtr = Message->Header.type;
    767   if (LenPtr != NULL) {
    768     *LenPtr = Message->Header.len;
    769   }
    770   Body = Message->u.Reply.Body;
    771 
    772   FreePool (Message);
    773   *Result = Body;
    774   return XENSTORE_STATUS_SUCCESS;
    775 }
    776 
    777 /**
    778   Send a message with an optionally muti-part body to the XenStore service.
    779 
    780   @param Transaction    The transaction to use for this request.
    781   @param RequestType    The type of message to send.
    782   @param WriteRequest   Pointers to the body sections of the request.
    783   @param NumRequests    The number of body sections in the request.
    784   @param LenPtr         The returned length of the reply.
    785   @param ResultPtr      The returned body of the reply.
    786 
    787   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
    788            the cause of failure.
    789 **/
    790 STATIC
    791 XENSTORE_STATUS
    792 XenStoreTalkv (
    793   IN  CONST XENSTORE_TRANSACTION *Transaction,
    794   IN  enum xsd_sockmsg_type   RequestType,
    795   IN  CONST WRITE_REQUEST     *WriteRequest,
    796   IN  UINT32                  NumRequests,
    797   OUT UINT32                  *LenPtr OPTIONAL,
    798   OUT VOID                    **ResultPtr OPTIONAL
    799   )
    800 {
    801   struct xsd_sockmsg Message;
    802   void *Return = NULL;
    803   UINT32 Index;
    804   XENSTORE_STATUS Status;
    805 
    806   if (Transaction == XST_NIL) {
    807     Message.tx_id = 0;
    808   } else {
    809     Message.tx_id = Transaction->Id;
    810   }
    811   Message.req_id = 0;
    812   Message.type = RequestType;
    813   Message.len = 0;
    814   for (Index = 0; Index < NumRequests; Index++) {
    815     Message.len += WriteRequest[Index].Len;
    816   }
    817 
    818   Status = XenStoreWriteStore (&Message, sizeof (Message));
    819   if (Status != XENSTORE_STATUS_SUCCESS) {
    820     DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
    821     goto Error;
    822   }
    823 
    824   for (Index = 0; Index < NumRequests; Index++) {
    825     Status = XenStoreWriteStore (WriteRequest[Index].Data, WriteRequest[Index].Len);
    826     if (Status != XENSTORE_STATUS_SUCCESS) {
    827       DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
    828       goto Error;
    829     }
    830   }
    831 
    832   Status = XenStoreReadReply ((enum xsd_sockmsg_type *)&Message.type, LenPtr, &Return);
    833 
    834 Error:
    835   if (Status != XENSTORE_STATUS_SUCCESS) {
    836     return Status;
    837   }
    838 
    839   if (Message.type == XS_ERROR) {
    840     Status = XenStoreGetError (Return);
    841     FreePool (Return);
    842     return Status;
    843   }
    844 
    845   /* Reply is either error or an echo of our request message type. */
    846   ASSERT ((enum xsd_sockmsg_type)Message.type == RequestType);
    847 
    848   if (ResultPtr) {
    849     *ResultPtr = Return;
    850   } else {
    851     FreePool (Return);
    852   }
    853 
    854   return XENSTORE_STATUS_SUCCESS;
    855 }
    856 
    857 /**
    858   Wrapper for XenStoreTalkv allowing easy transmission of a message with
    859   a single, contiguous, message body.
    860 
    861   The returned result is provided in malloced storage and thus must be free'd
    862   by the caller.
    863 
    864   @param Transaction    The transaction to use for this request.
    865   @param RequestType    The type of message to send.
    866   @param Body           The body of the request.
    867   @param LenPtr         The returned length of the reply.
    868   @param Result         The returned body of the reply.
    869 
    870   @return  0 on success.  Otherwise an errno indicating
    871            the cause of failure.
    872 **/
    873 STATIC
    874 XENSTORE_STATUS
    875 XenStoreSingle (
    876   IN  CONST XENSTORE_TRANSACTION *Transaction,
    877   IN  enum xsd_sockmsg_type   RequestType,
    878   IN  CONST CHAR8             *Body,
    879   OUT UINT32                  *LenPtr OPTIONAL,
    880   OUT VOID                    **Result OPTIONAL
    881   )
    882 {
    883   WRITE_REQUEST WriteRequest;
    884 
    885   WriteRequest.Data = (VOID *) Body;
    886   WriteRequest.Len = (UINT32)AsciiStrSize (Body);
    887 
    888   return XenStoreTalkv (Transaction, RequestType, &WriteRequest, 1,
    889                         LenPtr, Result);
    890 }
    891 
    892 //
    893 // XenStore Watch Support
    894 //
    895 
    896 /**
    897   Transmit a watch request to the XenStore service.
    898 
    899   @param Path    The path in the XenStore to watch.
    900   @param Tocken  A unique identifier for this watch.
    901 
    902   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating the
    903            cause of failure.
    904 **/
    905 STATIC
    906 XENSTORE_STATUS
    907 XenStoreWatch (
    908   CONST CHAR8 *Path,
    909   CONST CHAR8 *Token
    910   )
    911 {
    912   WRITE_REQUEST WriteRequest[2];
    913 
    914   WriteRequest[0].Data = (VOID *) Path;
    915   WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
    916   WriteRequest[1].Data = (VOID *) Token;
    917   WriteRequest[1].Len = (UINT32)AsciiStrSize (Token);
    918 
    919   return XenStoreTalkv (XST_NIL, XS_WATCH, WriteRequest, 2, NULL, NULL);
    920 }
    921 
    922 /**
    923   Transmit an uwatch request to the XenStore service.
    924 
    925   @param Path    The path in the XenStore to watch.
    926   @param Tocken  A unique identifier for this watch.
    927 
    928   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
    929            the cause of failure.
    930 **/
    931 STATIC
    932 XENSTORE_STATUS
    933 XenStoreUnwatch (
    934   CONST CHAR8 *Path,
    935   CONST CHAR8 *Token
    936   )
    937 {
    938   WRITE_REQUEST WriteRequest[2];
    939 
    940   WriteRequest[0].Data = (VOID *) Path;
    941   WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
    942   WriteRequest[1].Data = (VOID *) Token;
    943   WriteRequest[1].Len = (UINT32)AsciiStrSize (Token);
    944 
    945   return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL);
    946 }
    947 
    948 STATIC
    949 XENSTORE_STATUS
    950 XenStoreWaitWatch (
    951   VOID *Token
    952   )
    953 {
    954   XENSTORE_MESSAGE *Message;
    955   LIST_ENTRY *Entry = NULL;
    956   LIST_ENTRY *Last = NULL;
    957   XENSTORE_STATUS Status;
    958 
    959   while (TRUE) {
    960     EfiAcquireLock (&xs.WatchEventsLock);
    961     if (IsListEmpty (&xs.WatchEvents) ||
    962         Last == GetFirstNode (&xs.WatchEvents)) {
    963       EfiReleaseLock (&xs.WatchEventsLock);
    964       Status = XenStoreProcessMessage ();
    965       if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) {
    966         return Status;
    967       }
    968       continue;
    969     }
    970 
    971     for (Entry = GetFirstNode (&xs.WatchEvents);
    972          Entry != Last && !IsNull (&xs.WatchEvents, Entry);
    973          Entry = GetNextNode (&xs.WatchEvents, Entry)) {
    974       Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
    975       if (Message->u.Watch.Handle == Token) {
    976         RemoveEntryList (Entry);
    977         EfiReleaseLock (&xs.WatchEventsLock);
    978         FreePool((VOID*)Message->u.Watch.Vector);
    979         FreePool(Message);
    980         return XENSTORE_STATUS_SUCCESS;
    981       }
    982     }
    983     Last = GetFirstNode (&xs.WatchEvents);
    984     EfiReleaseLock (&xs.WatchEventsLock);
    985   }
    986 }
    987 
    988 VOID
    989 EFIAPI
    990 NotifyEventChannelCheckForEvent (
    991   IN EFI_EVENT Event,
    992   IN VOID *Context
    993   )
    994 {
    995   XENSTORE_PRIVATE *xsp;
    996   xsp = (XENSTORE_PRIVATE *)Context;
    997   if (TestAndClearBit (xsp->EventChannel, xsp->Dev->SharedInfo->evtchn_pending)) {
    998     gBS->SignalEvent (Event);
    999   }
   1000 }
   1001 
   1002 /**
   1003   Setup communication channels with the XenStore service.
   1004 
   1005   @retval EFI_SUCCESS if everything went well.
   1006 **/
   1007 STATIC
   1008 EFI_STATUS
   1009 XenStoreInitComms (
   1010   XENSTORE_PRIVATE *xsp
   1011   )
   1012 {
   1013   EFI_STATUS Status;
   1014   EFI_EVENT TimerEvent;
   1015   struct xenstore_domain_interface *XenStore = xsp->XenStore;
   1016 
   1017   Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
   1018   Status = gBS->SetTimer (TimerEvent, TimerRelative,
   1019                           EFI_TIMER_PERIOD_SECONDS (5));
   1020   while (XenStore->rsp_prod != XenStore->rsp_cons) {
   1021     Status = gBS->CheckEvent (TimerEvent);
   1022     if (!EFI_ERROR (Status)) {
   1023       DEBUG ((EFI_D_WARN, "XENSTORE response ring is not quiescent "
   1024               "(%08x:%08x): fixing up\n",
   1025               XenStore->rsp_cons, XenStore->rsp_prod));
   1026       XenStore->rsp_cons = XenStore->rsp_prod;
   1027     }
   1028   }
   1029   gBS->CloseEvent (TimerEvent);
   1030 
   1031   Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_NOTIFY,
   1032                              NotifyEventChannelCheckForEvent, xsp,
   1033                              &xsp->EventChannelEvent);
   1034   ASSERT_EFI_ERROR (Status);
   1035 
   1036   return Status;
   1037 }
   1038 
   1039 /**
   1040   Initialize XenStore.
   1041 
   1042   @param Dev  A XENBUS_DEVICE instance.
   1043 
   1044   @retval EFI_SUCCESS if everything went well.
   1045 **/
   1046 EFI_STATUS
   1047 XenStoreInit (
   1048   XENBUS_DEVICE *Dev
   1049   )
   1050 {
   1051   EFI_STATUS Status;
   1052   /**
   1053    * The HVM guest pseudo-physical frame number.  This is Xen's mapping
   1054    * of the true machine frame number into our "physical address space".
   1055    */
   1056   UINTN XenStoreGpfn;
   1057 
   1058   xs.Dev = Dev;
   1059 
   1060   xs.EventChannel = (evtchn_port_t)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN);
   1061   XenStoreGpfn = (UINTN)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN);
   1062   xs.XenStore = (VOID *) (XenStoreGpfn << EFI_PAGE_SHIFT);
   1063   DEBUG ((EFI_D_INFO, "XenBusInit: XenBus rings @%p, event channel %x\n",
   1064           xs.XenStore, xs.EventChannel));
   1065 
   1066   InitializeListHead (&xs.ReplyList);
   1067   InitializeListHead (&xs.WatchEvents);
   1068   InitializeListHead (&xs.RegisteredWatches);
   1069 
   1070   EfiInitializeLock (&xs.ReplyLock, TPL_NOTIFY);
   1071   EfiInitializeLock (&xs.RegisteredWatchesLock, TPL_NOTIFY);
   1072   EfiInitializeLock (&xs.WatchEventsLock, TPL_NOTIFY);
   1073 
   1074   /* Initialize the shared memory rings to talk to xenstored */
   1075   Status = XenStoreInitComms (&xs);
   1076   if (EFI_ERROR (Status)) {
   1077     return Status;
   1078   }
   1079 
   1080   return Status;
   1081 }
   1082 
   1083 VOID
   1084 XenStoreDeinit (
   1085   IN XENBUS_DEVICE *Dev
   1086   )
   1087 {
   1088   //
   1089   // Emptying the list RegisteredWatches, but this list should already be
   1090   // empty. Every driver that is using Watches should unregister them when
   1091   // it is stopped.
   1092   //
   1093   if (!IsListEmpty (&xs.RegisteredWatches)) {
   1094     XENSTORE_WATCH *Watch;
   1095     LIST_ENTRY *Entry;
   1096     DEBUG ((EFI_D_WARN, "XenStore: RegisteredWatches is not empty, cleaning up..."));
   1097     Entry = GetFirstNode (&xs.RegisteredWatches);
   1098     while (!IsNull (&xs.RegisteredWatches, Entry)) {
   1099       Watch = XENSTORE_WATCH_FROM_LINK (Entry);
   1100       Entry = GetNextNode (&xs.RegisteredWatches, Entry);
   1101 
   1102       XenStoreUnregisterWatch (Watch);
   1103     }
   1104   }
   1105 
   1106   //
   1107   // Emptying the list WatchEvents, but this list should already be empty after
   1108   // having cleanup the list RegisteredWatches.
   1109   //
   1110   if (!IsListEmpty (&xs.WatchEvents)) {
   1111     LIST_ENTRY *Entry;
   1112     DEBUG ((EFI_D_WARN, "XenStore: WatchEvents is not empty, cleaning up..."));
   1113     Entry = GetFirstNode (&xs.WatchEvents);
   1114     while (!IsNull (&xs.WatchEvents, Entry)) {
   1115       XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
   1116       Entry = GetNextNode (&xs.WatchEvents, Entry);
   1117       RemoveEntryList (&Message->Link);
   1118       FreePool ((VOID*)Message->u.Watch.Vector);
   1119       FreePool (Message);
   1120     }
   1121   }
   1122 
   1123   if (!IsListEmpty (&xs.ReplyList)) {
   1124     XENSTORE_MESSAGE *Message;
   1125     LIST_ENTRY *Entry;
   1126     Entry = GetFirstNode (&xs.ReplyList);
   1127     while (!IsNull (&xs.ReplyList, Entry)) {
   1128       Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
   1129       Entry = GetNextNode (&xs.ReplyList, Entry);
   1130       RemoveEntryList (&Message->Link);
   1131       FreePool (Message->u.Reply.Body);
   1132       FreePool (Message);
   1133     }
   1134   }
   1135 
   1136   gBS->CloseEvent (xs.EventChannelEvent);
   1137 
   1138   if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) {
   1139     xs.XenStore->connection = XENSTORE_RECONNECT;
   1140     XenEventChannelNotify (xs.Dev, xs.EventChannel);
   1141     while (*(volatile UINT32*)&xs.XenStore->connection == XENSTORE_RECONNECT) {
   1142       XenStoreWaitForEvent (xs.EventChannelEvent, EFI_TIMER_PERIOD_MILLISECONDS (100));
   1143     }
   1144   } else {
   1145     /* If the backend reads the state while we're erasing it then the
   1146      * ring state will become corrupted, preventing guest frontends from
   1147      * connecting. This is rare. To help diagnose the failure, we fill
   1148      * the ring with XS_INVALID packets. */
   1149     SetMem (xs.XenStore->req, XENSTORE_RING_SIZE, 0xff);
   1150     SetMem (xs.XenStore->rsp, XENSTORE_RING_SIZE, 0xff);
   1151     xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
   1152     xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
   1153   }
   1154   xs.XenStore = NULL;
   1155 }
   1156 
   1157 //
   1158 // Public API
   1159 // API comments for these methods can be found in XenStore.h
   1160 //
   1161 
   1162 XENSTORE_STATUS
   1163 XenStoreListDirectory (
   1164   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1165   IN  CONST CHAR8           *DirectoryPath,
   1166   IN  CONST CHAR8           *Node,
   1167   OUT UINT32                *DirectoryCountPtr,
   1168   OUT CONST CHAR8           ***DirectoryListPtr
   1169   )
   1170 {
   1171   CHAR8 *Path;
   1172   CHAR8 *TempStr;
   1173   UINT32 Len = 0;
   1174   XENSTORE_STATUS Status;
   1175 
   1176   Path = XenStoreJoin (DirectoryPath, Node);
   1177   Status = XenStoreSingle (Transaction, XS_DIRECTORY, Path, &Len,
   1178                            (VOID **) &TempStr);
   1179   FreePool (Path);
   1180   if (Status != XENSTORE_STATUS_SUCCESS) {
   1181     return Status;
   1182   }
   1183 
   1184   *DirectoryListPtr = Split (TempStr, Len, DirectoryCountPtr);
   1185 
   1186   return XENSTORE_STATUS_SUCCESS;
   1187 }
   1188 
   1189 BOOLEAN
   1190 XenStorePathExists (
   1191   IN CONST XENSTORE_TRANSACTION *Transaction,
   1192   IN CONST CHAR8           *Directory,
   1193   IN CONST CHAR8           *Node
   1194   )
   1195 {
   1196   CONST CHAR8 **TempStr;
   1197   XENSTORE_STATUS Status;
   1198   UINT32 TempNum;
   1199 
   1200   Status = XenStoreListDirectory (Transaction, Directory, Node,
   1201                                   &TempNum, &TempStr);
   1202   if (Status != XENSTORE_STATUS_SUCCESS) {
   1203     return FALSE;
   1204   }
   1205   FreePool ((VOID*)TempStr);
   1206   return TRUE;
   1207 }
   1208 
   1209 XENSTORE_STATUS
   1210 XenStoreRead (
   1211   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1212   IN  CONST CHAR8             *DirectoryPath,
   1213   IN  CONST CHAR8             *Node,
   1214   OUT UINT32                  *LenPtr OPTIONAL,
   1215   OUT VOID                    **Result
   1216   )
   1217 {
   1218   CHAR8 *Path;
   1219   VOID *Value;
   1220   XENSTORE_STATUS Status;
   1221 
   1222   Path = XenStoreJoin (DirectoryPath, Node);
   1223   Status = XenStoreSingle (Transaction, XS_READ, Path, LenPtr, &Value);
   1224   FreePool (Path);
   1225   if (Status != XENSTORE_STATUS_SUCCESS) {
   1226     return Status;
   1227   }
   1228 
   1229   *Result = Value;
   1230   return XENSTORE_STATUS_SUCCESS;
   1231 }
   1232 
   1233 XENSTORE_STATUS
   1234 XenStoreWrite (
   1235   IN CONST XENSTORE_TRANSACTION *Transaction,
   1236   IN CONST CHAR8           *DirectoryPath,
   1237   IN CONST CHAR8           *Node,
   1238   IN CONST CHAR8           *Str
   1239   )
   1240 {
   1241   CHAR8 *Path;
   1242   WRITE_REQUEST WriteRequest[2];
   1243   XENSTORE_STATUS Status;
   1244 
   1245   Path = XenStoreJoin (DirectoryPath, Node);
   1246 
   1247   WriteRequest[0].Data = (VOID *) Path;
   1248   WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
   1249   WriteRequest[1].Data = (VOID *) Str;
   1250   WriteRequest[1].Len = (UINT32)AsciiStrLen (Str);
   1251 
   1252   Status = XenStoreTalkv (Transaction, XS_WRITE, WriteRequest, 2, NULL, NULL);
   1253   FreePool (Path);
   1254 
   1255   return Status;
   1256 }
   1257 
   1258 XENSTORE_STATUS
   1259 XenStoreRemove (
   1260   IN CONST XENSTORE_TRANSACTION *Transaction,
   1261   IN CONST CHAR8            *DirectoryPath,
   1262   IN CONST CHAR8            *Node
   1263   )
   1264 {
   1265   CHAR8 *Path;
   1266   XENSTORE_STATUS Status;
   1267 
   1268   Path = XenStoreJoin (DirectoryPath, Node);
   1269   Status = XenStoreSingle (Transaction, XS_RM, Path, NULL, NULL);
   1270   FreePool (Path);
   1271 
   1272   return Status;
   1273 }
   1274 
   1275 XENSTORE_STATUS
   1276 XenStoreTransactionStart (
   1277   OUT XENSTORE_TRANSACTION  *Transaction
   1278   )
   1279 {
   1280   CHAR8 *IdStr;
   1281   XENSTORE_STATUS Status;
   1282 
   1283   Status = XenStoreSingle (XST_NIL, XS_TRANSACTION_START, "", NULL,
   1284                            (VOID **) &IdStr);
   1285   if (Status == XENSTORE_STATUS_SUCCESS) {
   1286     Transaction->Id = (UINT32)AsciiStrDecimalToUintn (IdStr);
   1287     FreePool (IdStr);
   1288   }
   1289 
   1290   return Status;
   1291 }
   1292 
   1293 XENSTORE_STATUS
   1294 XenStoreTransactionEnd (
   1295   IN CONST XENSTORE_TRANSACTION *Transaction,
   1296   IN BOOLEAN                Abort
   1297   )
   1298 {
   1299   CHAR8 AbortStr[2];
   1300 
   1301   if (Abort) {
   1302     AsciiStrCpy (AbortStr, "F");
   1303   } else {
   1304     AsciiStrCpy (AbortStr, "T");
   1305   }
   1306 
   1307   return XenStoreSingle (Transaction, XS_TRANSACTION_END, AbortStr, NULL, NULL);
   1308 }
   1309 
   1310 XENSTORE_STATUS
   1311 XenStoreVSPrint (
   1312   IN CONST XENSTORE_TRANSACTION *Transaction,
   1313   IN CONST CHAR8           *DirectoryPath,
   1314   IN CONST CHAR8           *Node,
   1315   IN CONST CHAR8           *FormatString,
   1316   IN VA_LIST               Marker
   1317   )
   1318 {
   1319   CHAR8 *Buf;
   1320   XENSTORE_STATUS Status;
   1321   UINTN BufSize;
   1322 
   1323   BufSize = SPrintLengthAsciiFormat (FormatString, Marker) + 1;
   1324   Buf = AllocateZeroPool (BufSize);
   1325   AsciiVSPrint (Buf, BufSize, FormatString, Marker);
   1326   Status = XenStoreWrite (Transaction, DirectoryPath, Node, Buf);
   1327   FreePool (Buf);
   1328 
   1329   return Status;
   1330 }
   1331 
   1332 XENSTORE_STATUS
   1333 EFIAPI
   1334 XenStoreSPrint (
   1335   IN CONST XENSTORE_TRANSACTION *Transaction,
   1336   IN CONST CHAR8            *DirectoryPath,
   1337   IN CONST CHAR8            *Node,
   1338   IN CONST CHAR8            *FormatString,
   1339   ...
   1340   )
   1341 {
   1342   VA_LIST Marker;
   1343   XENSTORE_STATUS Status;
   1344 
   1345   VA_START (Marker, FormatString);
   1346   Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
   1347   VA_END (Marker);
   1348 
   1349   return Status;
   1350 }
   1351 
   1352 XENSTORE_STATUS
   1353 XenStoreRegisterWatch (
   1354   IN CONST CHAR8      *DirectoryPath,
   1355   IN CONST CHAR8      *Node,
   1356   OUT XENSTORE_WATCH  **WatchPtr
   1357   )
   1358 {
   1359   /* Pointer in ascii is the token. */
   1360   CHAR8 Token[sizeof (XENSTORE_WATCH) * 2 + 1];
   1361   XENSTORE_STATUS Status;
   1362   XENSTORE_WATCH *Watch;
   1363 
   1364   Watch = AllocateZeroPool (sizeof (XENSTORE_WATCH));
   1365   Watch->Signature = XENSTORE_WATCH_SIGNATURE;
   1366   Watch->Node = XenStoreJoin (DirectoryPath, Node);
   1367 
   1368   EfiAcquireLock (&xs.RegisteredWatchesLock);
   1369   InsertTailList (&xs.RegisteredWatches, &Watch->Link);
   1370   EfiReleaseLock (&xs.RegisteredWatchesLock);
   1371 
   1372   AsciiSPrint (Token, sizeof (Token), "%p", (VOID*) Watch);
   1373   Status = XenStoreWatch (Watch->Node, Token);
   1374 
   1375   /* Ignore errors due to multiple registration. */
   1376   if (Status == XENSTORE_STATUS_EEXIST) {
   1377     Status = XENSTORE_STATUS_SUCCESS;
   1378   }
   1379 
   1380   if (Status == XENSTORE_STATUS_SUCCESS) {
   1381     *WatchPtr = Watch;
   1382   } else {
   1383     EfiAcquireLock (&xs.RegisteredWatchesLock);
   1384     RemoveEntryList (&Watch->Link);
   1385     EfiReleaseLock (&xs.RegisteredWatchesLock);
   1386     FreePool (Watch->Node);
   1387     FreePool (Watch);
   1388   }
   1389 
   1390   return Status;
   1391 }
   1392 
   1393 VOID
   1394 XenStoreUnregisterWatch (
   1395   IN XENSTORE_WATCH *Watch
   1396   )
   1397 {
   1398   CHAR8 Token[sizeof (Watch) * 2 + 1];
   1399   LIST_ENTRY *Entry;
   1400 
   1401   ASSERT (Watch->Signature == XENSTORE_WATCH_SIGNATURE);
   1402 
   1403   AsciiSPrint (Token, sizeof (Token), "%p", (VOID *) Watch);
   1404   if (XenStoreFindWatch (Token) == NULL) {
   1405     return;
   1406   }
   1407 
   1408   EfiAcquireLock (&xs.RegisteredWatchesLock);
   1409   RemoveEntryList (&Watch->Link);
   1410   EfiReleaseLock (&xs.RegisteredWatchesLock);
   1411 
   1412   XenStoreUnwatch (Watch->Node, Token);
   1413 
   1414   /* Cancel pending watch events. */
   1415   EfiAcquireLock (&xs.WatchEventsLock);
   1416   Entry = GetFirstNode (&xs.WatchEvents);
   1417   while (!IsNull (&xs.WatchEvents, Entry)) {
   1418     XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
   1419     Entry = GetNextNode (&xs.WatchEvents, Entry);
   1420     if (Message->u.Watch.Handle == Watch) {
   1421       RemoveEntryList (&Message->Link);
   1422       FreePool ((VOID*)Message->u.Watch.Vector);
   1423       FreePool (Message);
   1424     }
   1425   }
   1426   EfiReleaseLock (&xs.WatchEventsLock);
   1427 
   1428   FreePool (Watch->Node);
   1429   FreePool (Watch);
   1430 }
   1431 
   1432 
   1433 //
   1434 // XENBUS protocol
   1435 //
   1436 
   1437 XENSTORE_STATUS
   1438 EFIAPI
   1439 XenBusWaitForWatch (
   1440   IN XENBUS_PROTOCOL *This,
   1441   IN VOID *Token
   1442   )
   1443 {
   1444   return XenStoreWaitWatch (Token);
   1445 }
   1446 
   1447 XENSTORE_STATUS
   1448 EFIAPI
   1449 XenBusXenStoreRead (
   1450   IN  XENBUS_PROTOCOL       *This,
   1451   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1452   IN  CONST CHAR8           *Node,
   1453   OUT VOID                  **Value
   1454   )
   1455 {
   1456   return XenStoreRead (Transaction, This->Node, Node, NULL, Value);
   1457 }
   1458 
   1459 XENSTORE_STATUS
   1460 EFIAPI
   1461 XenBusXenStoreBackendRead (
   1462   IN  XENBUS_PROTOCOL       *This,
   1463   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1464   IN  CONST CHAR8           *Node,
   1465   OUT VOID                  **Value
   1466   )
   1467 {
   1468   return XenStoreRead (Transaction, This->Backend, Node, NULL, Value);
   1469 }
   1470 
   1471 XENSTORE_STATUS
   1472 EFIAPI
   1473 XenBusXenStoreRemove (
   1474   IN XENBUS_PROTOCOL        *This,
   1475   IN CONST XENSTORE_TRANSACTION *Transaction,
   1476   IN const char             *Node
   1477   )
   1478 {
   1479   return XenStoreRemove (Transaction, This->Node, Node);
   1480 }
   1481 
   1482 XENSTORE_STATUS
   1483 EFIAPI
   1484 XenBusXenStoreTransactionStart (
   1485   IN  XENBUS_PROTOCOL       *This,
   1486   OUT XENSTORE_TRANSACTION  *Transaction
   1487   )
   1488 {
   1489   return XenStoreTransactionStart (Transaction);
   1490 }
   1491 
   1492 XENSTORE_STATUS
   1493 EFIAPI
   1494 XenBusXenStoreTransactionEnd (
   1495   IN XENBUS_PROTOCOL        *This,
   1496   IN CONST XENSTORE_TRANSACTION *Transaction,
   1497   IN BOOLEAN                Abort
   1498   )
   1499 {
   1500   return XenStoreTransactionEnd (Transaction, Abort);
   1501 }
   1502 
   1503 XENSTORE_STATUS
   1504 EFIAPI
   1505 XenBusXenStoreSPrint (
   1506   IN XENBUS_PROTOCOL        *This,
   1507   IN CONST XENSTORE_TRANSACTION *Transaction,
   1508   IN CONST CHAR8            *DirectoryPath,
   1509   IN CONST CHAR8            *Node,
   1510   IN CONST CHAR8            *FormatString,
   1511   ...
   1512   )
   1513 {
   1514   VA_LIST Marker;
   1515   XENSTORE_STATUS Status;
   1516 
   1517   VA_START (Marker, FormatString);
   1518   Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
   1519   VA_END (Marker);
   1520 
   1521   return Status;
   1522 }
   1523 
   1524 XENSTORE_STATUS
   1525 EFIAPI
   1526 XenBusRegisterWatch (
   1527   IN  XENBUS_PROTOCOL *This,
   1528   IN  CONST CHAR8     *Node,
   1529   OUT VOID            **Token
   1530   )
   1531 {
   1532   return XenStoreRegisterWatch (This->Node, Node, (XENSTORE_WATCH **) Token);
   1533 }
   1534 
   1535 XENSTORE_STATUS
   1536 EFIAPI
   1537 XenBusRegisterWatchBackend (
   1538   IN  XENBUS_PROTOCOL *This,
   1539   IN  CONST CHAR8     *Node,
   1540   OUT VOID            **Token
   1541   )
   1542 {
   1543   return XenStoreRegisterWatch (This->Backend, Node, (XENSTORE_WATCH **) Token);
   1544 }
   1545 
   1546 VOID
   1547 EFIAPI
   1548 XenBusUnregisterWatch (
   1549   IN XENBUS_PROTOCOL  *This,
   1550   IN VOID             *Token
   1551   )
   1552 {
   1553   XenStoreUnregisterWatch ((XENSTORE_WATCH *) Token);
   1554 }
   1555