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 hierarchy
     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   UINTN BufSize;
    307 
    308   /* +1 for '/' and +1 for '\0' */
    309   BufSize = AsciiStrLen (DirectoryPath) + AsciiStrLen (Node) + 2;
    310   Buf = AllocatePool (BufSize);
    311   ASSERT (Buf != NULL);
    312 
    313   if (Node[0] == '\0') {
    314     AsciiSPrint (Buf, BufSize, "%a", DirectoryPath);
    315   } else {
    316     AsciiSPrint (Buf, BufSize, "%a/%a", DirectoryPath, Node);
    317   }
    318 
    319   return Buf;
    320 }
    321 
    322 //
    323 // Low Level Communication Management
    324 //
    325 
    326 /**
    327   Verify that the indexes for a ring are valid.
    328 
    329   The difference between the producer and consumer cannot
    330   exceed the size of the ring.
    331 
    332   @param Cons  The consumer index for the ring to test.
    333   @param Prod  The producer index for the ring to test.
    334 
    335   @retval TRUE   If indexes are in range.
    336   @retval FALSE  If the indexes are out of range.
    337 **/
    338 STATIC
    339 BOOLEAN
    340 XenStoreCheckIndexes (
    341   XENSTORE_RING_IDX Cons,
    342   XENSTORE_RING_IDX Prod
    343   )
    344 {
    345   return ((Prod - Cons) <= XENSTORE_RING_SIZE);
    346 }
    347 
    348 /**
    349   Return a pointer to, and the length of, the contiguous
    350   free region available for output in a ring buffer.
    351 
    352   @param Cons    The consumer index for the ring.
    353   @param Prod    The producer index for the ring.
    354   @param Buffer  The base address of the ring's storage.
    355   @param LenPtr  The amount of contiguous storage available.
    356 
    357   @return  A pointer to the start location of the free region.
    358 **/
    359 STATIC
    360 VOID *
    361 XenStoreGetOutputChunk (
    362   IN  XENSTORE_RING_IDX Cons,
    363   IN  XENSTORE_RING_IDX Prod,
    364   IN  CHAR8             *Buffer,
    365   OUT UINT32            *LenPtr
    366   )
    367 {
    368   UINT32 Len;
    369   Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Prod);
    370   if ((XENSTORE_RING_SIZE - (Prod - Cons)) < Len) {
    371     Len = XENSTORE_RING_SIZE - (Prod - Cons);
    372   }
    373   *LenPtr = Len;
    374   return (Buffer + MASK_XENSTORE_IDX (Prod));
    375 }
    376 
    377 /**
    378   Return a pointer to, and the length of, the contiguous
    379   data available to read from a ring buffer.
    380 
    381   @param Cons    The consumer index for the ring.
    382   @param Prod    The producer index for the ring.
    383   @param Buffer  The base address of the ring's storage.
    384   @param LenPtr  The amount of contiguous data available to read.
    385 
    386   @return  A pointer to the start location of the available data.
    387 **/
    388 STATIC
    389 CONST VOID *
    390 XenStoreGetInputChunk (
    391   IN  XENSTORE_RING_IDX Cons,
    392   IN  XENSTORE_RING_IDX Prod,
    393   IN  CONST CHAR8       *Buffer,
    394   OUT UINT32            *LenPtr
    395   )
    396 {
    397   UINT32 Len;
    398 
    399   Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Cons);
    400   if ((Prod - Cons) < Len) {
    401     Len = Prod - Cons;
    402   }
    403   *LenPtr = Len;
    404   return (Buffer + MASK_XENSTORE_IDX (Cons));
    405 }
    406 
    407 /**
    408   Wait for an event or timeout.
    409 
    410   @param Event    Event to wait for.
    411   @param Timeout  A timeout value in 100ns units.
    412 
    413   @retval EFI_SUCCESS   Event have been triggered or the current TPL is not
    414                         TPL_APPLICATION.
    415   @retval EFI_TIMEOUT   Timeout have expired.
    416 **/
    417 STATIC
    418 EFI_STATUS
    419 XenStoreWaitForEvent (
    420   IN EFI_EVENT Event,
    421   IN UINT64    Timeout
    422   )
    423 {
    424   UINTN Index;
    425   EFI_STATUS Status;
    426   EFI_EVENT TimerEvent;
    427   EFI_EVENT WaitList[2];
    428 
    429   gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
    430   gBS->SetTimer (TimerEvent, TimerRelative, Timeout);
    431 
    432   WaitList[0] = xs.EventChannelEvent;
    433   WaitList[1] = TimerEvent;
    434   Status = gBS->WaitForEvent (2, WaitList, &Index);
    435   ASSERT (Status != EFI_INVALID_PARAMETER);
    436   gBS->CloseEvent (TimerEvent);
    437   if (Status == EFI_UNSUPPORTED) {
    438     return EFI_SUCCESS;
    439   }
    440   if (Index == 1) {
    441     return EFI_TIMEOUT;
    442   } else {
    443     return EFI_SUCCESS;
    444   }
    445 }
    446 
    447 /**
    448   Transmit data to the XenStore service.
    449 
    450   The buffer pointed to by DataPtr is at least Len bytes in length.
    451 
    452   @param DataPtr  A pointer to the contiguous data to send.
    453   @param Len      The amount of data to send.
    454 
    455   @return  On success 0, otherwise an errno value indicating the
    456            cause of failure.
    457 **/
    458 STATIC
    459 XENSTORE_STATUS
    460 XenStoreWriteStore (
    461   IN CONST VOID *DataPtr,
    462   IN UINT32     Len
    463   )
    464 {
    465   XENSTORE_RING_IDX Cons, Prod;
    466   CONST CHAR8 *Data = (CONST CHAR8 *)DataPtr;
    467 
    468   while (Len != 0) {
    469     void *Dest;
    470     UINT32 Available;
    471 
    472     Cons = xs.XenStore->req_cons;
    473     Prod = xs.XenStore->req_prod;
    474     if ((Prod - Cons) == XENSTORE_RING_SIZE) {
    475       /*
    476        * Output ring is full. Wait for a ring event.
    477        *
    478        * Note that the events from both queues are combined, so being woken
    479        * does not guarantee that data exist in the read ring.
    480        */
    481       EFI_STATUS Status;
    482 
    483       Status = XenStoreWaitForEvent (xs.EventChannelEvent,
    484                                      EFI_TIMER_PERIOD_SECONDS (1));
    485       if (Status == EFI_TIMEOUT) {
    486         DEBUG ((EFI_D_WARN, "XenStore Write, waiting for a ring event.\n"));
    487       }
    488       continue;
    489     }
    490 
    491     /* Verify queue sanity. */
    492     if (!XenStoreCheckIndexes (Cons, Prod)) {
    493       xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
    494       return XENSTORE_STATUS_EIO;
    495     }
    496 
    497     Dest = XenStoreGetOutputChunk (Cons, Prod, xs.XenStore->req, &Available);
    498     if (Available > Len) {
    499       Available = Len;
    500     }
    501 
    502     CopyMem (Dest, Data, Available);
    503     Data += Available;
    504     Len -= Available;
    505 
    506     /*
    507      * The store to the producer index, which indicates
    508      * to the other side that new data has arrived, must
    509      * be visible only after our copy of the data into the
    510      * ring has completed.
    511      */
    512     MemoryFence ();
    513     xs.XenStore->req_prod += Available;
    514 
    515     /*
    516      * The other side will see the change to req_prod at the time of the
    517      * interrupt.
    518      */
    519     MemoryFence ();
    520     XenEventChannelNotify (xs.Dev, xs.EventChannel);
    521   }
    522 
    523   return XENSTORE_STATUS_SUCCESS;
    524 }
    525 
    526 /**
    527   Receive data from the XenStore service.
    528 
    529   The buffer pointed to by DataPtr is at least Len bytes in length.
    530 
    531   @param DataPtr  A pointer to the contiguous buffer to receive the data.
    532   @param Len      The amount of data to receive.
    533 
    534   @return  On success 0, otherwise an errno value indicating the
    535            cause of failure.
    536 **/
    537 STATIC
    538 XENSTORE_STATUS
    539 XenStoreReadStore (
    540   OUT VOID *DataPtr,
    541   IN  UINT32 Len
    542   )
    543 {
    544   XENSTORE_RING_IDX Cons, Prod;
    545   CHAR8 *Data = (CHAR8 *) DataPtr;
    546 
    547   while (Len != 0) {
    548     UINT32 Available;
    549     CONST CHAR8 *Src;
    550 
    551     Cons = xs.XenStore->rsp_cons;
    552     Prod = xs.XenStore->rsp_prod;
    553     if (Cons == Prod) {
    554       /*
    555        * Nothing to read. Wait for a ring event.
    556        *
    557        * Note that the events from both queues are combined, so being woken
    558        * does not guarantee that data exist in the read ring.
    559        */
    560       EFI_STATUS Status;
    561 
    562       Status = XenStoreWaitForEvent (xs.EventChannelEvent,
    563                                      EFI_TIMER_PERIOD_SECONDS (1));
    564       if (Status == EFI_TIMEOUT) {
    565         DEBUG ((EFI_D_WARN, "XenStore Read, waiting for a ring event.\n"));
    566       }
    567       continue;
    568     }
    569 
    570     /* Verify queue sanity. */
    571     if (!XenStoreCheckIndexes (Cons, Prod)) {
    572       xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
    573       return XENSTORE_STATUS_EIO;
    574     }
    575 
    576     Src = XenStoreGetInputChunk (Cons, Prod, xs.XenStore->rsp, &Available);
    577     if (Available > Len) {
    578       Available = Len;
    579     }
    580 
    581     /*
    582      * Insure the data we read is related to the indexes
    583      * we read above.
    584      */
    585     MemoryFence ();
    586 
    587     CopyMem (Data, Src, Available);
    588     Data += Available;
    589     Len -= Available;
    590 
    591     /*
    592      * Insure that the producer of this ring does not see
    593      * the ring space as free until after we have copied it
    594      * out.
    595      */
    596     MemoryFence ();
    597     xs.XenStore->rsp_cons += Available;
    598 
    599     /*
    600      * The producer will see the updated consumer index when the event is
    601      * delivered.
    602      */
    603     MemoryFence ();
    604     XenEventChannelNotify (xs.Dev, xs.EventChannel);
    605   }
    606 
    607   return XENSTORE_STATUS_SUCCESS;
    608 }
    609 
    610 //
    611 // Received Message Processing
    612 //
    613 
    614 /**
    615   Block reading the next message from the XenStore service and
    616   process the result.
    617 
    618   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno value
    619            indicating the type of failure encountered.
    620 **/
    621 STATIC
    622 XENSTORE_STATUS
    623 XenStoreProcessMessage (
    624   VOID
    625   )
    626 {
    627   XENSTORE_MESSAGE *Message;
    628   CHAR8 *Body;
    629   XENSTORE_STATUS Status;
    630 
    631   Message = AllocateZeroPool (sizeof (XENSTORE_MESSAGE));
    632   Message->Signature = XENSTORE_MESSAGE_SIGNATURE;
    633   Status = XenStoreReadStore (&Message->Header, sizeof (Message->Header));
    634   if (Status != XENSTORE_STATUS_SUCCESS) {
    635     FreePool (Message);
    636     DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
    637     return Status;
    638   }
    639 
    640   Body = AllocatePool (Message->Header.len + 1);
    641   Status = XenStoreReadStore (Body, Message->Header.len);
    642   if (Status != XENSTORE_STATUS_SUCCESS) {
    643     FreePool (Body);
    644     FreePool (Message);
    645     DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
    646     return Status;
    647   }
    648   Body[Message->Header.len] = '\0';
    649 
    650   if (Message->Header.type == XS_WATCH_EVENT) {
    651     Message->u.Watch.Vector = Split(Body, Message->Header.len,
    652                                     &Message->u.Watch.VectorSize);
    653 
    654     EfiAcquireLock (&xs.RegisteredWatchesLock);
    655     Message->u.Watch.Handle =
    656       XenStoreFindWatch (Message->u.Watch.Vector[XS_WATCH_TOKEN]);
    657     DEBUG ((EFI_D_INFO, "XenStore: Watch event %a\n",
    658             Message->u.Watch.Vector[XS_WATCH_TOKEN]));
    659     if (Message->u.Watch.Handle != NULL) {
    660       EfiAcquireLock (&xs.WatchEventsLock);
    661       InsertHeadList (&xs.WatchEvents, &Message->Link);
    662       EfiReleaseLock (&xs.WatchEventsLock);
    663     } else {
    664       DEBUG ((EFI_D_WARN, "XenStore: Watch handle %a not found\n",
    665               Message->u.Watch.Vector[XS_WATCH_TOKEN]));
    666       FreePool((VOID*)Message->u.Watch.Vector);
    667       FreePool(Message);
    668     }
    669     EfiReleaseLock (&xs.RegisteredWatchesLock);
    670   } else {
    671     Message->u.Reply.Body = Body;
    672     EfiAcquireLock (&xs.ReplyLock);
    673     InsertTailList (&xs.ReplyList, &Message->Link);
    674     EfiReleaseLock (&xs.ReplyLock);
    675   }
    676 
    677   return XENSTORE_STATUS_SUCCESS;
    678 }
    679 
    680 //
    681 // XenStore Message Request/Reply Processing
    682 //
    683 
    684 /**
    685   Convert a XenStore error string into an errno number.
    686 
    687   Unknown error strings are converted to EINVAL.
    688 
    689   @param errorstring  The error string to convert.
    690 
    691   @return  The errno best matching the input string.
    692 
    693 **/
    694 typedef struct {
    695   XENSTORE_STATUS Status;
    696   CONST CHAR8 *ErrorStr;
    697 } XenStoreErrors;
    698 
    699 static XenStoreErrors gXenStoreErrors[] = {
    700   { XENSTORE_STATUS_EINVAL, "EINVAL" },
    701   { XENSTORE_STATUS_EACCES, "EACCES" },
    702   { XENSTORE_STATUS_EEXIST, "EEXIST" },
    703   { XENSTORE_STATUS_EISDIR, "EISDIR" },
    704   { XENSTORE_STATUS_ENOENT, "ENOENT" },
    705   { XENSTORE_STATUS_ENOMEM, "ENOMEM" },
    706   { XENSTORE_STATUS_ENOSPC, "ENOSPC" },
    707   { XENSTORE_STATUS_EIO, "EIO" },
    708   { XENSTORE_STATUS_ENOTEMPTY, "ENOTEMPTY" },
    709   { XENSTORE_STATUS_ENOSYS, "ENOSYS" },
    710   { XENSTORE_STATUS_EROFS, "EROFS" },
    711   { XENSTORE_STATUS_EBUSY, "EBUSY" },
    712   { XENSTORE_STATUS_EAGAIN, "EAGAIN" },
    713   { XENSTORE_STATUS_EISCONN, "EISCONN" },
    714   { XENSTORE_STATUS_E2BIG, "E2BIG" }
    715 };
    716 
    717 STATIC
    718 XENSTORE_STATUS
    719 XenStoreGetError (
    720   CONST CHAR8 *ErrorStr
    721   )
    722 {
    723   UINT32 Index;
    724 
    725   for (Index = 0; Index < ARRAY_SIZE(gXenStoreErrors); Index++) {
    726     if (!AsciiStrCmp (ErrorStr, gXenStoreErrors[Index].ErrorStr)) {
    727       return gXenStoreErrors[Index].Status;
    728     }
    729   }
    730   DEBUG ((EFI_D_WARN, "XenStore gave unknown error %a\n", ErrorStr));
    731   return XENSTORE_STATUS_EINVAL;
    732 }
    733 
    734 /**
    735   Block waiting for a reply to a message request.
    736 
    737   @param TypePtr The returned type of the reply.
    738   @param LenPtr  The returned body length of the reply.
    739   @param Result  The returned body of the reply.
    740 **/
    741 STATIC
    742 XENSTORE_STATUS
    743 XenStoreReadReply (
    744   OUT enum xsd_sockmsg_type *TypePtr,
    745   OUT UINT32 *LenPtr OPTIONAL,
    746   OUT VOID **Result
    747   )
    748 {
    749   XENSTORE_MESSAGE *Message;
    750   LIST_ENTRY *Entry;
    751   CHAR8 *Body;
    752 
    753   while (IsListEmpty (&xs.ReplyList)) {
    754     XENSTORE_STATUS Status;
    755     Status = XenStoreProcessMessage ();
    756     if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) {
    757       DEBUG ((EFI_D_ERROR, "XenStore, error while reading the ring (%d).",
    758               Status));
    759       return Status;
    760     }
    761   }
    762   EfiAcquireLock (&xs.ReplyLock);
    763   Entry = GetFirstNode (&xs.ReplyList);
    764   Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
    765   RemoveEntryList (Entry);
    766   EfiReleaseLock (&xs.ReplyLock);
    767 
    768   *TypePtr = Message->Header.type;
    769   if (LenPtr != NULL) {
    770     *LenPtr = Message->Header.len;
    771   }
    772   Body = Message->u.Reply.Body;
    773 
    774   FreePool (Message);
    775   *Result = Body;
    776   return XENSTORE_STATUS_SUCCESS;
    777 }
    778 
    779 /**
    780   Send a message with an optionally muti-part body to the XenStore service.
    781 
    782   @param Transaction    The transaction to use for this request.
    783   @param RequestType    The type of message to send.
    784   @param WriteRequest   Pointers to the body sections of the request.
    785   @param NumRequests    The number of body sections in the request.
    786   @param LenPtr         The returned length of the reply.
    787   @param ResultPtr      The returned body of the reply.
    788 
    789   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
    790            the cause of failure.
    791 **/
    792 STATIC
    793 XENSTORE_STATUS
    794 XenStoreTalkv (
    795   IN  CONST XENSTORE_TRANSACTION *Transaction,
    796   IN  enum xsd_sockmsg_type   RequestType,
    797   IN  CONST WRITE_REQUEST     *WriteRequest,
    798   IN  UINT32                  NumRequests,
    799   OUT UINT32                  *LenPtr OPTIONAL,
    800   OUT VOID                    **ResultPtr OPTIONAL
    801   )
    802 {
    803   struct xsd_sockmsg Message;
    804   void *Return = NULL;
    805   UINT32 Index;
    806   XENSTORE_STATUS Status;
    807 
    808   if (Transaction == XST_NIL) {
    809     Message.tx_id = 0;
    810   } else {
    811     Message.tx_id = Transaction->Id;
    812   }
    813   Message.req_id = 0;
    814   Message.type = RequestType;
    815   Message.len = 0;
    816   for (Index = 0; Index < NumRequests; Index++) {
    817     Message.len += WriteRequest[Index].Len;
    818   }
    819 
    820   Status = XenStoreWriteStore (&Message, sizeof (Message));
    821   if (Status != XENSTORE_STATUS_SUCCESS) {
    822     DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
    823     goto Error;
    824   }
    825 
    826   for (Index = 0; Index < NumRequests; Index++) {
    827     Status = XenStoreWriteStore (WriteRequest[Index].Data, WriteRequest[Index].Len);
    828     if (Status != XENSTORE_STATUS_SUCCESS) {
    829       DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
    830       goto Error;
    831     }
    832   }
    833 
    834   Status = XenStoreReadReply ((enum xsd_sockmsg_type *)&Message.type, LenPtr, &Return);
    835 
    836 Error:
    837   if (Status != XENSTORE_STATUS_SUCCESS) {
    838     return Status;
    839   }
    840 
    841   if (Message.type == XS_ERROR) {
    842     Status = XenStoreGetError (Return);
    843     FreePool (Return);
    844     return Status;
    845   }
    846 
    847   /* Reply is either error or an echo of our request message type. */
    848   ASSERT ((enum xsd_sockmsg_type)Message.type == RequestType);
    849 
    850   if (ResultPtr) {
    851     *ResultPtr = Return;
    852   } else {
    853     FreePool (Return);
    854   }
    855 
    856   return XENSTORE_STATUS_SUCCESS;
    857 }
    858 
    859 /**
    860   Wrapper for XenStoreTalkv allowing easy transmission of a message with
    861   a single, contiguous, message body.
    862 
    863   The returned result is provided in malloced storage and thus must be free'd
    864   by the caller.
    865 
    866   @param Transaction    The transaction to use for this request.
    867   @param RequestType    The type of message to send.
    868   @param Body           The body of the request.
    869   @param LenPtr         The returned length of the reply.
    870   @param Result         The returned body of the reply.
    871 
    872   @return  0 on success.  Otherwise an errno indicating
    873            the cause of failure.
    874 **/
    875 STATIC
    876 XENSTORE_STATUS
    877 XenStoreSingle (
    878   IN  CONST XENSTORE_TRANSACTION *Transaction,
    879   IN  enum xsd_sockmsg_type   RequestType,
    880   IN  CONST CHAR8             *Body,
    881   OUT UINT32                  *LenPtr OPTIONAL,
    882   OUT VOID                    **Result OPTIONAL
    883   )
    884 {
    885   WRITE_REQUEST WriteRequest;
    886 
    887   WriteRequest.Data = (VOID *) Body;
    888   WriteRequest.Len = (UINT32)AsciiStrSize (Body);
    889 
    890   return XenStoreTalkv (Transaction, RequestType, &WriteRequest, 1,
    891                         LenPtr, Result);
    892 }
    893 
    894 //
    895 // XenStore Watch Support
    896 //
    897 
    898 /**
    899   Transmit a watch request to the XenStore service.
    900 
    901   @param Path    The path in the XenStore to watch.
    902   @param Tocken  A unique identifier for this watch.
    903 
    904   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating the
    905            cause of failure.
    906 **/
    907 STATIC
    908 XENSTORE_STATUS
    909 XenStoreWatch (
    910   CONST CHAR8 *Path,
    911   CONST CHAR8 *Token
    912   )
    913 {
    914   WRITE_REQUEST WriteRequest[2];
    915 
    916   WriteRequest[0].Data = (VOID *) Path;
    917   WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
    918   WriteRequest[1].Data = (VOID *) Token;
    919   WriteRequest[1].Len = (UINT32)AsciiStrSize (Token);
    920 
    921   return XenStoreTalkv (XST_NIL, XS_WATCH, WriteRequest, 2, NULL, NULL);
    922 }
    923 
    924 /**
    925   Transmit an uwatch request to the XenStore service.
    926 
    927   @param Path    The path in the XenStore to watch.
    928   @param Tocken  A unique identifier for this watch.
    929 
    930   @return  XENSTORE_STATUS_SUCCESS on success.  Otherwise an errno indicating
    931            the cause of failure.
    932 **/
    933 STATIC
    934 XENSTORE_STATUS
    935 XenStoreUnwatch (
    936   CONST CHAR8 *Path,
    937   CONST CHAR8 *Token
    938   )
    939 {
    940   WRITE_REQUEST WriteRequest[2];
    941 
    942   WriteRequest[0].Data = (VOID *) Path;
    943   WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
    944   WriteRequest[1].Data = (VOID *) Token;
    945   WriteRequest[1].Len = (UINT32)AsciiStrSize (Token);
    946 
    947   return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL);
    948 }
    949 
    950 STATIC
    951 XENSTORE_STATUS
    952 XenStoreWaitWatch (
    953   VOID *Token
    954   )
    955 {
    956   XENSTORE_MESSAGE *Message;
    957   LIST_ENTRY *Entry = NULL;
    958   LIST_ENTRY *Last = NULL;
    959   XENSTORE_STATUS Status;
    960 
    961   while (TRUE) {
    962     EfiAcquireLock (&xs.WatchEventsLock);
    963     if (IsListEmpty (&xs.WatchEvents) ||
    964         Last == GetFirstNode (&xs.WatchEvents)) {
    965       EfiReleaseLock (&xs.WatchEventsLock);
    966       Status = XenStoreProcessMessage ();
    967       if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) {
    968         return Status;
    969       }
    970       continue;
    971     }
    972 
    973     for (Entry = GetFirstNode (&xs.WatchEvents);
    974          Entry != Last && !IsNull (&xs.WatchEvents, Entry);
    975          Entry = GetNextNode (&xs.WatchEvents, Entry)) {
    976       Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
    977       if (Message->u.Watch.Handle == Token) {
    978         RemoveEntryList (Entry);
    979         EfiReleaseLock (&xs.WatchEventsLock);
    980         FreePool((VOID*)Message->u.Watch.Vector);
    981         FreePool(Message);
    982         return XENSTORE_STATUS_SUCCESS;
    983       }
    984     }
    985     Last = GetFirstNode (&xs.WatchEvents);
    986     EfiReleaseLock (&xs.WatchEventsLock);
    987   }
    988 }
    989 
    990 VOID
    991 EFIAPI
    992 NotifyEventChannelCheckForEvent (
    993   IN EFI_EVENT Event,
    994   IN VOID *Context
    995   )
    996 {
    997   XENSTORE_PRIVATE *xsp;
    998   xsp = (XENSTORE_PRIVATE *)Context;
    999   if (TestAndClearBit (xsp->EventChannel, xsp->Dev->SharedInfo->evtchn_pending)) {
   1000     gBS->SignalEvent (Event);
   1001   }
   1002 }
   1003 
   1004 /**
   1005   Setup communication channels with the XenStore service.
   1006 
   1007   @retval EFI_SUCCESS if everything went well.
   1008 **/
   1009 STATIC
   1010 EFI_STATUS
   1011 XenStoreInitComms (
   1012   XENSTORE_PRIVATE *xsp
   1013   )
   1014 {
   1015   EFI_STATUS Status;
   1016   EFI_EVENT TimerEvent;
   1017   struct xenstore_domain_interface *XenStore = xsp->XenStore;
   1018 
   1019   Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
   1020   Status = gBS->SetTimer (TimerEvent, TimerRelative,
   1021                           EFI_TIMER_PERIOD_SECONDS (5));
   1022   while (XenStore->rsp_prod != XenStore->rsp_cons) {
   1023     Status = gBS->CheckEvent (TimerEvent);
   1024     if (!EFI_ERROR (Status)) {
   1025       DEBUG ((EFI_D_WARN, "XENSTORE response ring is not quiescent "
   1026               "(%08x:%08x): fixing up\n",
   1027               XenStore->rsp_cons, XenStore->rsp_prod));
   1028       XenStore->rsp_cons = XenStore->rsp_prod;
   1029     }
   1030   }
   1031   gBS->CloseEvent (TimerEvent);
   1032 
   1033   Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_NOTIFY,
   1034                              NotifyEventChannelCheckForEvent, xsp,
   1035                              &xsp->EventChannelEvent);
   1036   ASSERT_EFI_ERROR (Status);
   1037 
   1038   return Status;
   1039 }
   1040 
   1041 /**
   1042   Initialize XenStore.
   1043 
   1044   @param Dev  A XENBUS_DEVICE instance.
   1045 
   1046   @retval EFI_SUCCESS if everything went well.
   1047 **/
   1048 EFI_STATUS
   1049 XenStoreInit (
   1050   XENBUS_DEVICE *Dev
   1051   )
   1052 {
   1053   EFI_STATUS Status;
   1054   /**
   1055    * The HVM guest pseudo-physical frame number.  This is Xen's mapping
   1056    * of the true machine frame number into our "physical address space".
   1057    */
   1058   UINTN XenStoreGpfn;
   1059 
   1060   xs.Dev = Dev;
   1061 
   1062   xs.EventChannel = (evtchn_port_t)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN);
   1063   XenStoreGpfn = (UINTN)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN);
   1064   xs.XenStore = (VOID *) (XenStoreGpfn << EFI_PAGE_SHIFT);
   1065   DEBUG ((EFI_D_INFO, "XenBusInit: XenBus rings @%p, event channel %x\n",
   1066           xs.XenStore, xs.EventChannel));
   1067 
   1068   InitializeListHead (&xs.ReplyList);
   1069   InitializeListHead (&xs.WatchEvents);
   1070   InitializeListHead (&xs.RegisteredWatches);
   1071 
   1072   EfiInitializeLock (&xs.ReplyLock, TPL_NOTIFY);
   1073   EfiInitializeLock (&xs.RegisteredWatchesLock, TPL_NOTIFY);
   1074   EfiInitializeLock (&xs.WatchEventsLock, TPL_NOTIFY);
   1075 
   1076   /* Initialize the shared memory rings to talk to xenstored */
   1077   Status = XenStoreInitComms (&xs);
   1078   if (EFI_ERROR (Status)) {
   1079     return Status;
   1080   }
   1081 
   1082   return Status;
   1083 }
   1084 
   1085 VOID
   1086 XenStoreDeinit (
   1087   IN XENBUS_DEVICE *Dev
   1088   )
   1089 {
   1090   //
   1091   // Emptying the list RegisteredWatches, but this list should already be
   1092   // empty. Every driver that is using Watches should unregister them when
   1093   // it is stopped.
   1094   //
   1095   if (!IsListEmpty (&xs.RegisteredWatches)) {
   1096     XENSTORE_WATCH *Watch;
   1097     LIST_ENTRY *Entry;
   1098     DEBUG ((EFI_D_WARN, "XenStore: RegisteredWatches is not empty, cleaning up..."));
   1099     Entry = GetFirstNode (&xs.RegisteredWatches);
   1100     while (!IsNull (&xs.RegisteredWatches, Entry)) {
   1101       Watch = XENSTORE_WATCH_FROM_LINK (Entry);
   1102       Entry = GetNextNode (&xs.RegisteredWatches, Entry);
   1103 
   1104       XenStoreUnregisterWatch (Watch);
   1105     }
   1106   }
   1107 
   1108   //
   1109   // Emptying the list WatchEvents, but this list should already be empty after
   1110   // having cleanup the list RegisteredWatches.
   1111   //
   1112   if (!IsListEmpty (&xs.WatchEvents)) {
   1113     LIST_ENTRY *Entry;
   1114     DEBUG ((EFI_D_WARN, "XenStore: WatchEvents is not empty, cleaning up..."));
   1115     Entry = GetFirstNode (&xs.WatchEvents);
   1116     while (!IsNull (&xs.WatchEvents, Entry)) {
   1117       XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
   1118       Entry = GetNextNode (&xs.WatchEvents, Entry);
   1119       RemoveEntryList (&Message->Link);
   1120       FreePool ((VOID*)Message->u.Watch.Vector);
   1121       FreePool (Message);
   1122     }
   1123   }
   1124 
   1125   if (!IsListEmpty (&xs.ReplyList)) {
   1126     XENSTORE_MESSAGE *Message;
   1127     LIST_ENTRY *Entry;
   1128     Entry = GetFirstNode (&xs.ReplyList);
   1129     while (!IsNull (&xs.ReplyList, Entry)) {
   1130       Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
   1131       Entry = GetNextNode (&xs.ReplyList, Entry);
   1132       RemoveEntryList (&Message->Link);
   1133       FreePool (Message->u.Reply.Body);
   1134       FreePool (Message);
   1135     }
   1136   }
   1137 
   1138   gBS->CloseEvent (xs.EventChannelEvent);
   1139 
   1140   if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) {
   1141     xs.XenStore->connection = XENSTORE_RECONNECT;
   1142     XenEventChannelNotify (xs.Dev, xs.EventChannel);
   1143     while (*(volatile UINT32*)&xs.XenStore->connection == XENSTORE_RECONNECT) {
   1144       XenStoreWaitForEvent (xs.EventChannelEvent, EFI_TIMER_PERIOD_MILLISECONDS (100));
   1145     }
   1146   } else {
   1147     /* If the backend reads the state while we're erasing it then the
   1148      * ring state will become corrupted, preventing guest frontends from
   1149      * connecting. This is rare. To help diagnose the failure, we fill
   1150      * the ring with XS_INVALID packets. */
   1151     SetMem (xs.XenStore->req, XENSTORE_RING_SIZE, 0xff);
   1152     SetMem (xs.XenStore->rsp, XENSTORE_RING_SIZE, 0xff);
   1153     xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
   1154     xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
   1155   }
   1156   xs.XenStore = NULL;
   1157 }
   1158 
   1159 //
   1160 // Public API
   1161 // API comments for these methods can be found in XenStore.h
   1162 //
   1163 
   1164 XENSTORE_STATUS
   1165 XenStoreListDirectory (
   1166   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1167   IN  CONST CHAR8           *DirectoryPath,
   1168   IN  CONST CHAR8           *Node,
   1169   OUT UINT32                *DirectoryCountPtr,
   1170   OUT CONST CHAR8           ***DirectoryListPtr
   1171   )
   1172 {
   1173   CHAR8 *Path;
   1174   CHAR8 *TempStr;
   1175   UINT32 Len = 0;
   1176   XENSTORE_STATUS Status;
   1177 
   1178   Path = XenStoreJoin (DirectoryPath, Node);
   1179   Status = XenStoreSingle (Transaction, XS_DIRECTORY, Path, &Len,
   1180                            (VOID **) &TempStr);
   1181   FreePool (Path);
   1182   if (Status != XENSTORE_STATUS_SUCCESS) {
   1183     return Status;
   1184   }
   1185 
   1186   *DirectoryListPtr = Split (TempStr, Len, DirectoryCountPtr);
   1187 
   1188   return XENSTORE_STATUS_SUCCESS;
   1189 }
   1190 
   1191 BOOLEAN
   1192 XenStorePathExists (
   1193   IN CONST XENSTORE_TRANSACTION *Transaction,
   1194   IN CONST CHAR8           *Directory,
   1195   IN CONST CHAR8           *Node
   1196   )
   1197 {
   1198   CONST CHAR8 **TempStr;
   1199   XENSTORE_STATUS Status;
   1200   UINT32 TempNum;
   1201 
   1202   Status = XenStoreListDirectory (Transaction, Directory, Node,
   1203                                   &TempNum, &TempStr);
   1204   if (Status != XENSTORE_STATUS_SUCCESS) {
   1205     return FALSE;
   1206   }
   1207   FreePool ((VOID*)TempStr);
   1208   return TRUE;
   1209 }
   1210 
   1211 XENSTORE_STATUS
   1212 XenStoreRead (
   1213   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1214   IN  CONST CHAR8             *DirectoryPath,
   1215   IN  CONST CHAR8             *Node,
   1216   OUT UINT32                  *LenPtr OPTIONAL,
   1217   OUT VOID                    **Result
   1218   )
   1219 {
   1220   CHAR8 *Path;
   1221   VOID *Value;
   1222   XENSTORE_STATUS Status;
   1223 
   1224   Path = XenStoreJoin (DirectoryPath, Node);
   1225   Status = XenStoreSingle (Transaction, XS_READ, Path, LenPtr, &Value);
   1226   FreePool (Path);
   1227   if (Status != XENSTORE_STATUS_SUCCESS) {
   1228     return Status;
   1229   }
   1230 
   1231   *Result = Value;
   1232   return XENSTORE_STATUS_SUCCESS;
   1233 }
   1234 
   1235 XENSTORE_STATUS
   1236 XenStoreWrite (
   1237   IN CONST XENSTORE_TRANSACTION *Transaction,
   1238   IN CONST CHAR8           *DirectoryPath,
   1239   IN CONST CHAR8           *Node,
   1240   IN CONST CHAR8           *Str
   1241   )
   1242 {
   1243   CHAR8 *Path;
   1244   WRITE_REQUEST WriteRequest[2];
   1245   XENSTORE_STATUS Status;
   1246 
   1247   Path = XenStoreJoin (DirectoryPath, Node);
   1248 
   1249   WriteRequest[0].Data = (VOID *) Path;
   1250   WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
   1251   WriteRequest[1].Data = (VOID *) Str;
   1252   WriteRequest[1].Len = (UINT32)AsciiStrLen (Str);
   1253 
   1254   Status = XenStoreTalkv (Transaction, XS_WRITE, WriteRequest, 2, NULL, NULL);
   1255   FreePool (Path);
   1256 
   1257   return Status;
   1258 }
   1259 
   1260 XENSTORE_STATUS
   1261 XenStoreRemove (
   1262   IN CONST XENSTORE_TRANSACTION *Transaction,
   1263   IN CONST CHAR8            *DirectoryPath,
   1264   IN CONST CHAR8            *Node
   1265   )
   1266 {
   1267   CHAR8 *Path;
   1268   XENSTORE_STATUS Status;
   1269 
   1270   Path = XenStoreJoin (DirectoryPath, Node);
   1271   Status = XenStoreSingle (Transaction, XS_RM, Path, NULL, NULL);
   1272   FreePool (Path);
   1273 
   1274   return Status;
   1275 }
   1276 
   1277 XENSTORE_STATUS
   1278 XenStoreTransactionStart (
   1279   OUT XENSTORE_TRANSACTION  *Transaction
   1280   )
   1281 {
   1282   CHAR8 *IdStr;
   1283   XENSTORE_STATUS Status;
   1284 
   1285   Status = XenStoreSingle (XST_NIL, XS_TRANSACTION_START, "", NULL,
   1286                            (VOID **) &IdStr);
   1287   if (Status == XENSTORE_STATUS_SUCCESS) {
   1288     Transaction->Id = (UINT32)AsciiStrDecimalToUintn (IdStr);
   1289     FreePool (IdStr);
   1290   }
   1291 
   1292   return Status;
   1293 }
   1294 
   1295 XENSTORE_STATUS
   1296 XenStoreTransactionEnd (
   1297   IN CONST XENSTORE_TRANSACTION *Transaction,
   1298   IN BOOLEAN                Abort
   1299   )
   1300 {
   1301   CHAR8 AbortStr[2];
   1302 
   1303   AbortStr[0] = Abort ? 'F' : 'T';
   1304   AbortStr[1] = '\0';
   1305 
   1306   return XenStoreSingle (Transaction, XS_TRANSACTION_END, AbortStr, NULL, NULL);
   1307 }
   1308 
   1309 XENSTORE_STATUS
   1310 XenStoreVSPrint (
   1311   IN CONST XENSTORE_TRANSACTION *Transaction,
   1312   IN CONST CHAR8           *DirectoryPath,
   1313   IN CONST CHAR8           *Node,
   1314   IN CONST CHAR8           *FormatString,
   1315   IN VA_LIST               Marker
   1316   )
   1317 {
   1318   CHAR8 *Buf;
   1319   XENSTORE_STATUS Status;
   1320   UINTN BufSize;
   1321   VA_LIST Marker2;
   1322 
   1323   VA_COPY (Marker2, Marker);
   1324   BufSize = SPrintLengthAsciiFormat (FormatString, Marker2) + 1;
   1325   VA_END (Marker2);
   1326   Buf = AllocateZeroPool (BufSize);
   1327   AsciiVSPrint (Buf, BufSize, FormatString, Marker);
   1328   Status = XenStoreWrite (Transaction, DirectoryPath, Node, Buf);
   1329   FreePool (Buf);
   1330 
   1331   return Status;
   1332 }
   1333 
   1334 XENSTORE_STATUS
   1335 EFIAPI
   1336 XenStoreSPrint (
   1337   IN CONST XENSTORE_TRANSACTION *Transaction,
   1338   IN CONST CHAR8            *DirectoryPath,
   1339   IN CONST CHAR8            *Node,
   1340   IN CONST CHAR8            *FormatString,
   1341   ...
   1342   )
   1343 {
   1344   VA_LIST Marker;
   1345   XENSTORE_STATUS Status;
   1346 
   1347   VA_START (Marker, FormatString);
   1348   Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
   1349   VA_END (Marker);
   1350 
   1351   return Status;
   1352 }
   1353 
   1354 XENSTORE_STATUS
   1355 XenStoreRegisterWatch (
   1356   IN CONST CHAR8      *DirectoryPath,
   1357   IN CONST CHAR8      *Node,
   1358   OUT XENSTORE_WATCH  **WatchPtr
   1359   )
   1360 {
   1361   /* Pointer in ascii is the token. */
   1362   CHAR8 Token[sizeof (XENSTORE_WATCH) * 2 + 1];
   1363   XENSTORE_STATUS Status;
   1364   XENSTORE_WATCH *Watch;
   1365 
   1366   Watch = AllocateZeroPool (sizeof (XENSTORE_WATCH));
   1367   Watch->Signature = XENSTORE_WATCH_SIGNATURE;
   1368   Watch->Node = XenStoreJoin (DirectoryPath, Node);
   1369 
   1370   EfiAcquireLock (&xs.RegisteredWatchesLock);
   1371   InsertTailList (&xs.RegisteredWatches, &Watch->Link);
   1372   EfiReleaseLock (&xs.RegisteredWatchesLock);
   1373 
   1374   AsciiSPrint (Token, sizeof (Token), "%p", (VOID*) Watch);
   1375   Status = XenStoreWatch (Watch->Node, Token);
   1376 
   1377   /* Ignore errors due to multiple registration. */
   1378   if (Status == XENSTORE_STATUS_EEXIST) {
   1379     Status = XENSTORE_STATUS_SUCCESS;
   1380   }
   1381 
   1382   if (Status == XENSTORE_STATUS_SUCCESS) {
   1383     *WatchPtr = Watch;
   1384   } else {
   1385     EfiAcquireLock (&xs.RegisteredWatchesLock);
   1386     RemoveEntryList (&Watch->Link);
   1387     EfiReleaseLock (&xs.RegisteredWatchesLock);
   1388     FreePool (Watch->Node);
   1389     FreePool (Watch);
   1390   }
   1391 
   1392   return Status;
   1393 }
   1394 
   1395 VOID
   1396 XenStoreUnregisterWatch (
   1397   IN XENSTORE_WATCH *Watch
   1398   )
   1399 {
   1400   CHAR8 Token[sizeof (Watch) * 2 + 1];
   1401   LIST_ENTRY *Entry;
   1402 
   1403   ASSERT (Watch->Signature == XENSTORE_WATCH_SIGNATURE);
   1404 
   1405   AsciiSPrint (Token, sizeof (Token), "%p", (VOID *) Watch);
   1406   if (XenStoreFindWatch (Token) == NULL) {
   1407     return;
   1408   }
   1409 
   1410   EfiAcquireLock (&xs.RegisteredWatchesLock);
   1411   RemoveEntryList (&Watch->Link);
   1412   EfiReleaseLock (&xs.RegisteredWatchesLock);
   1413 
   1414   XenStoreUnwatch (Watch->Node, Token);
   1415 
   1416   /* Cancel pending watch events. */
   1417   EfiAcquireLock (&xs.WatchEventsLock);
   1418   Entry = GetFirstNode (&xs.WatchEvents);
   1419   while (!IsNull (&xs.WatchEvents, Entry)) {
   1420     XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
   1421     Entry = GetNextNode (&xs.WatchEvents, Entry);
   1422     if (Message->u.Watch.Handle == Watch) {
   1423       RemoveEntryList (&Message->Link);
   1424       FreePool ((VOID*)Message->u.Watch.Vector);
   1425       FreePool (Message);
   1426     }
   1427   }
   1428   EfiReleaseLock (&xs.WatchEventsLock);
   1429 
   1430   FreePool (Watch->Node);
   1431   FreePool (Watch);
   1432 }
   1433 
   1434 
   1435 //
   1436 // XENBUS protocol
   1437 //
   1438 
   1439 XENSTORE_STATUS
   1440 EFIAPI
   1441 XenBusWaitForWatch (
   1442   IN XENBUS_PROTOCOL *This,
   1443   IN VOID *Token
   1444   )
   1445 {
   1446   return XenStoreWaitWatch (Token);
   1447 }
   1448 
   1449 XENSTORE_STATUS
   1450 EFIAPI
   1451 XenBusXenStoreRead (
   1452   IN  XENBUS_PROTOCOL       *This,
   1453   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1454   IN  CONST CHAR8           *Node,
   1455   OUT VOID                  **Value
   1456   )
   1457 {
   1458   return XenStoreRead (Transaction, This->Node, Node, NULL, Value);
   1459 }
   1460 
   1461 XENSTORE_STATUS
   1462 EFIAPI
   1463 XenBusXenStoreBackendRead (
   1464   IN  XENBUS_PROTOCOL       *This,
   1465   IN  CONST XENSTORE_TRANSACTION *Transaction,
   1466   IN  CONST CHAR8           *Node,
   1467   OUT VOID                  **Value
   1468   )
   1469 {
   1470   return XenStoreRead (Transaction, This->Backend, Node, NULL, Value);
   1471 }
   1472 
   1473 XENSTORE_STATUS
   1474 EFIAPI
   1475 XenBusXenStoreRemove (
   1476   IN XENBUS_PROTOCOL        *This,
   1477   IN CONST XENSTORE_TRANSACTION *Transaction,
   1478   IN const char             *Node
   1479   )
   1480 {
   1481   return XenStoreRemove (Transaction, This->Node, Node);
   1482 }
   1483 
   1484 XENSTORE_STATUS
   1485 EFIAPI
   1486 XenBusXenStoreTransactionStart (
   1487   IN  XENBUS_PROTOCOL       *This,
   1488   OUT XENSTORE_TRANSACTION  *Transaction
   1489   )
   1490 {
   1491   return XenStoreTransactionStart (Transaction);
   1492 }
   1493 
   1494 XENSTORE_STATUS
   1495 EFIAPI
   1496 XenBusXenStoreTransactionEnd (
   1497   IN XENBUS_PROTOCOL        *This,
   1498   IN CONST XENSTORE_TRANSACTION *Transaction,
   1499   IN BOOLEAN                Abort
   1500   )
   1501 {
   1502   return XenStoreTransactionEnd (Transaction, Abort);
   1503 }
   1504 
   1505 XENSTORE_STATUS
   1506 EFIAPI
   1507 XenBusXenStoreSPrint (
   1508   IN XENBUS_PROTOCOL        *This,
   1509   IN CONST XENSTORE_TRANSACTION *Transaction,
   1510   IN CONST CHAR8            *DirectoryPath,
   1511   IN CONST CHAR8            *Node,
   1512   IN CONST CHAR8            *FormatString,
   1513   ...
   1514   )
   1515 {
   1516   VA_LIST Marker;
   1517   XENSTORE_STATUS Status;
   1518 
   1519   VA_START (Marker, FormatString);
   1520   Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
   1521   VA_END (Marker);
   1522 
   1523   return Status;
   1524 }
   1525 
   1526 XENSTORE_STATUS
   1527 EFIAPI
   1528 XenBusRegisterWatch (
   1529   IN  XENBUS_PROTOCOL *This,
   1530   IN  CONST CHAR8     *Node,
   1531   OUT VOID            **Token
   1532   )
   1533 {
   1534   return XenStoreRegisterWatch (This->Node, Node, (XENSTORE_WATCH **) Token);
   1535 }
   1536 
   1537 XENSTORE_STATUS
   1538 EFIAPI
   1539 XenBusRegisterWatchBackend (
   1540   IN  XENBUS_PROTOCOL *This,
   1541   IN  CONST CHAR8     *Node,
   1542   OUT VOID            **Token
   1543   )
   1544 {
   1545   return XenStoreRegisterWatch (This->Backend, Node, (XENSTORE_WATCH **) Token);
   1546 }
   1547 
   1548 VOID
   1549 EFIAPI
   1550 XenBusUnregisterWatch (
   1551   IN XENBUS_PROTOCOL  *This,
   1552   IN VOID             *Token
   1553   )
   1554 {
   1555   XenStoreUnregisterWatch ((XENSTORE_WATCH *) Token);
   1556 }
   1557