2 Low-level kernel interface to the XenStore.
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
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.
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
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.
28 Several Xen services depend on the XenStore, most notably the
29 XenBus used to discover and manage Xen devices.
31 Copyright (C) 2005 Rusty Russell, IBM Corporation
32 Copyright (C) 2009,2010 Spectra Logic Corporation
33 Copyright (C) 2014, Citrix Ltd.
35 This file may be distributed separately from the Linux kernel, or
36 incorporated into other software packages, subject to the following license:
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:
45 The above copyright notice and this permission notice shall be included in
46 all copies or substantial portions of the Software.
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
59 #include <Library/PrintLib.h>
61 #include <IndustryStandard/Xen/hvm/params.h>
63 #include "EventChannel.h"
64 #include <Library/XenHypercallLib.h>
67 // Private Data Structures
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
82 /* Path being watched. */
86 #define XENSTORE_WATCH_FROM_LINK(l) \
87 CR (l, XENSTORE_WATCH, Link, XENSTORE_WATCH_SIGNATURE)
91 * Structure capturing messages received from the XenStore service.
93 #define XENSTORE_MESSAGE_SIGNATURE SIGNATURE_32 ('X', 'S', 's', 'm')
98 struct xsd_sockmsg Header
;
101 /* Queued replies. */
106 /* Queued watch events. */
108 XENSTORE_WATCH
*Handle
;
109 CONST CHAR8
**Vector
;
114 #define XENSTORE_MESSAGE_FROM_LINK(r) \
115 CR (r, XENSTORE_MESSAGE, Link, XENSTORE_MESSAGE_SIGNATURE)
118 * Container for all XenStore related state.
122 * Pointer to shared memory communication structures allowing us
123 * to communicate with the XenStore service.
125 struct xenstore_domain_interface
*XenStore
;
130 * A list of replies to our requests.
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 ().
137 * /note Only one requesting context can be active at a time.
139 LIST_ENTRY ReplyList
;
141 /** Lock protecting the reply list. */
145 * List of registered watches.
147 LIST_ENTRY RegisteredWatches
;
149 /** Lock protecting the registered watches list. */
150 EFI_LOCK RegisteredWatchesLock
;
153 * List of pending watch callback events.
155 LIST_ENTRY WatchEvents
;
157 /** Lock protecting the watch calback list. */
158 EFI_LOCK WatchEventsLock
;
161 * The event channel for communicating with the
164 evtchn_port_t EventChannel
;
166 /** Handle for XenStore events. */
167 EFI_EVENT EventChannelEvent
;
173 static XENSTORE_PRIVATE xs
;
177 // Private Utility Functions
181 Count and optionally record pointers to a number of NUL terminated
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.
188 @return A count of the number of strings found.
193 IN CONST CHAR8
*Strings
,
195 OUT CONST CHAR8
**Dst OPTIONAL
201 for (Ptr
= Strings
; Ptr
< Strings
+ Len
; Ptr
+= AsciiStrSize (Ptr
)) {
212 Convert a contiguous buffer containing a series of NUL terminated
213 strings into an array of pointers to strings.
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.
219 The storage addressed by Strings is free'd prior to Split returning.
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
226 @return An array of pointers to the strings found in the input buffer.
238 ASSERT(NumPtr
!= NULL
);
239 ASSERT(Strings
!= NULL
);
241 /* Protect against unterminated buffers. */
243 Strings
[Len
- 1] = '\0';
246 /* Count the Strings. */
247 *NumPtr
= ExtractStrings (Strings
, Len
, NULL
);
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
);
254 /* Extract pointers to newly allocated array. */
255 Strings
= (CHAR8
*) &Dst
[*NumPtr
];
256 ExtractStrings (Strings
, Len
, Dst
);
262 Convert from watch token (unique identifier) to the associated
263 internal tracking structure for this watch.
265 @param Tocken The unique identifier for the watch to find.
267 @return A pointer to the found watch structure or NULL.
272 IN CONST CHAR8
*Token
275 XENSTORE_WATCH
*Watch
, *WantedWatch
;
278 WantedWatch
= (VOID
*) AsciiStrHexToUintn (Token
);
280 if (IsListEmpty (&xs
.RegisteredWatches
)) {
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
)
295 // Public Utility Functions
296 // API comments for these methods can be found in XenStore.h
301 IN CONST CHAR8
*DirectoryPath
,
308 /* +1 for '/' and +1 for '\0' */
309 BufSize
= AsciiStrLen (DirectoryPath
) + AsciiStrLen (Node
) + 2;
310 Buf
= AllocatePool (BufSize
);
311 ASSERT (Buf
!= NULL
);
313 if (Node
[0] == '\0') {
314 AsciiSPrint (Buf
, BufSize
, "%a", DirectoryPath
);
316 AsciiSPrint (Buf
, BufSize
, "%a/%a", DirectoryPath
, Node
);
323 // Low Level Communication Management
327 Verify that the indexes for a ring are valid.
329 The difference between the producer and consumer cannot
330 exceed the size of the ring.
332 @param Cons The consumer index for the ring to test.
333 @param Prod The producer index for the ring to test.
335 @retval TRUE If indexes are in range.
336 @retval FALSE If the indexes are out of range.
340 XenStoreCheckIndexes (
341 XENSTORE_RING_IDX Cons
,
342 XENSTORE_RING_IDX Prod
345 return ((Prod
- Cons
) <= XENSTORE_RING_SIZE
);
349 Return a pointer to, and the length of, the contiguous
350 free region available for output in a ring buffer.
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.
357 @return A pointer to the start location of the free region.
361 XenStoreGetOutputChunk (
362 IN XENSTORE_RING_IDX Cons
,
363 IN XENSTORE_RING_IDX Prod
,
369 Len
= XENSTORE_RING_SIZE
- MASK_XENSTORE_IDX (Prod
);
370 if ((XENSTORE_RING_SIZE
- (Prod
- Cons
)) < Len
) {
371 Len
= XENSTORE_RING_SIZE
- (Prod
- Cons
);
374 return (Buffer
+ MASK_XENSTORE_IDX (Prod
));
378 Return a pointer to, and the length of, the contiguous
379 data available to read from a ring buffer.
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.
386 @return A pointer to the start location of the available data.
390 XenStoreGetInputChunk (
391 IN XENSTORE_RING_IDX Cons
,
392 IN XENSTORE_RING_IDX Prod
,
393 IN CONST CHAR8
*Buffer
,
399 Len
= XENSTORE_RING_SIZE
- MASK_XENSTORE_IDX (Cons
);
400 if ((Prod
- Cons
) < Len
) {
404 return (Buffer
+ MASK_XENSTORE_IDX (Cons
));
408 Wait for an event or timeout.
410 @param Event Event to wait for.
411 @param Timeout A timeout value in 100ns units.
413 @retval EFI_SUCCESS Event have been triggered or the current TPL is not
415 @retval EFI_TIMEOUT Timeout have expired.
419 XenStoreWaitForEvent (
426 EFI_EVENT TimerEvent
;
427 EFI_EVENT WaitList
[2];
429 gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
430 gBS
->SetTimer (TimerEvent
, TimerRelative
, Timeout
);
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
) {
448 Transmit data to the XenStore service.
450 The buffer pointed to by DataPtr is at least Len bytes in length.
452 @param DataPtr A pointer to the contiguous data to send.
453 @param Len The amount of data to send.
455 @return On success 0, otherwise an errno value indicating the
461 IN CONST VOID
*DataPtr
,
465 XENSTORE_RING_IDX Cons
, Prod
;
466 CONST CHAR8
*Data
= (CONST CHAR8
*)DataPtr
;
472 Cons
= xs
.XenStore
->req_cons
;
473 Prod
= xs
.XenStore
->req_prod
;
474 if ((Prod
- Cons
) == XENSTORE_RING_SIZE
) {
476 * Output ring is full. Wait for a ring event.
478 * Note that the events from both queues are combined, so being woken
479 * does not guarantee that data exist in the read ring.
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"));
491 /* Verify queue sanity. */
492 if (!XenStoreCheckIndexes (Cons
, Prod
)) {
493 xs
.XenStore
->req_cons
= xs
.XenStore
->req_prod
= 0;
494 return XENSTORE_STATUS_EIO
;
497 Dest
= XenStoreGetOutputChunk (Cons
, Prod
, xs
.XenStore
->req
, &Available
);
498 if (Available
> Len
) {
502 CopyMem (Dest
, Data
, Available
);
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.
513 xs
.XenStore
->req_prod
+= Available
;
516 * The other side will see the change to req_prod at the time of the
520 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
523 return XENSTORE_STATUS_SUCCESS
;
527 Receive data from the XenStore service.
529 The buffer pointed to by DataPtr is at least Len bytes in length.
531 @param DataPtr A pointer to the contiguous buffer to receive the data.
532 @param Len The amount of data to receive.
534 @return On success 0, otherwise an errno value indicating the
544 XENSTORE_RING_IDX Cons
, Prod
;
545 CHAR8
*Data
= (CHAR8
*) DataPtr
;
551 Cons
= xs
.XenStore
->rsp_cons
;
552 Prod
= xs
.XenStore
->rsp_prod
;
555 * Nothing to read. Wait for a ring event.
557 * Note that the events from both queues are combined, so being woken
558 * does not guarantee that data exist in the read ring.
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"));
570 /* Verify queue sanity. */
571 if (!XenStoreCheckIndexes (Cons
, Prod
)) {
572 xs
.XenStore
->rsp_cons
= xs
.XenStore
->rsp_prod
= 0;
573 return XENSTORE_STATUS_EIO
;
576 Src
= XenStoreGetInputChunk (Cons
, Prod
, xs
.XenStore
->rsp
, &Available
);
577 if (Available
> Len
) {
582 * Insure the data we read is related to the indexes
587 CopyMem (Data
, Src
, Available
);
592 * Insure that the producer of this ring does not see
593 * the ring space as free until after we have copied it
597 xs
.XenStore
->rsp_cons
+= Available
;
600 * The producer will see the updated consumer index when the event is
604 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
607 return XENSTORE_STATUS_SUCCESS
;
611 // Received Message Processing
615 Block reading the next message from the XenStore service and
618 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno value
619 indicating the type of failure encountered.
623 XenStoreProcessMessage (
627 XENSTORE_MESSAGE
*Message
;
629 XENSTORE_STATUS Status
;
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
) {
636 DEBUG ((EFI_D_ERROR
, "XenStore: Error read store (%d)\n", Status
));
640 Body
= AllocatePool (Message
->Header
.len
+ 1);
641 Status
= XenStoreReadStore (Body
, Message
->Header
.len
);
642 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
645 DEBUG ((EFI_D_ERROR
, "XenStore: Error read store (%d)\n", Status
));
648 Body
[Message
->Header
.len
] = '\0';
650 if (Message
->Header
.type
== XS_WATCH_EVENT
) {
651 Message
->u
.Watch
.Vector
= Split(Body
, Message
->Header
.len
,
652 &Message
->u
.Watch
.VectorSize
);
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
);
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
);
669 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
671 Message
->u
.Reply
.Body
= Body
;
672 EfiAcquireLock (&xs
.ReplyLock
);
673 InsertTailList (&xs
.ReplyList
, &Message
->Link
);
674 EfiReleaseLock (&xs
.ReplyLock
);
677 return XENSTORE_STATUS_SUCCESS
;
681 // XenStore Message Request/Reply Processing
685 Convert a XenStore error string into an errno number.
687 Unknown error strings are converted to EINVAL.
689 @param errorstring The error string to convert.
691 @return The errno best matching the input string.
695 XENSTORE_STATUS Status
;
696 CONST CHAR8
*ErrorStr
;
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" }
716 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
721 CONST CHAR8
*ErrorStr
726 for (Index
= 0; Index
< ARRAY_SIZE(gXenStoreErrors
); Index
++) {
727 if (!AsciiStrCmp (ErrorStr
, gXenStoreErrors
[Index
].ErrorStr
)) {
728 return gXenStoreErrors
[Index
].Status
;
731 DEBUG ((EFI_D_WARN
, "XenStore gave unknown error %a\n", ErrorStr
));
732 return XENSTORE_STATUS_EINVAL
;
736 Block waiting for a reply to a message request.
738 @param TypePtr The returned type of the reply.
739 @param LenPtr The returned body length of the reply.
740 @param Result The returned body of the reply.
745 OUT
enum xsd_sockmsg_type
*TypePtr
,
746 OUT UINT32
*LenPtr OPTIONAL
,
750 XENSTORE_MESSAGE
*Message
;
754 while (IsListEmpty (&xs
.ReplyList
)) {
755 XENSTORE_STATUS Status
;
756 Status
= XenStoreProcessMessage ();
757 if (Status
!= XENSTORE_STATUS_SUCCESS
&& Status
!= XENSTORE_STATUS_EAGAIN
) {
758 DEBUG ((EFI_D_ERROR
, "XenStore, error while reading the ring (%d).",
763 EfiAcquireLock (&xs
.ReplyLock
);
764 Entry
= GetFirstNode (&xs
.ReplyList
);
765 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
766 RemoveEntryList (Entry
);
767 EfiReleaseLock (&xs
.ReplyLock
);
769 *TypePtr
= Message
->Header
.type
;
770 if (LenPtr
!= NULL
) {
771 *LenPtr
= Message
->Header
.len
;
773 Body
= Message
->u
.Reply
.Body
;
777 return XENSTORE_STATUS_SUCCESS
;
781 Send a message with an optionally muti-part body to the XenStore service.
783 @param Transaction The transaction to use for this request.
784 @param RequestType The type of message to send.
785 @param WriteRequest Pointers to the body sections of the request.
786 @param NumRequests The number of body sections in the request.
787 @param LenPtr The returned length of the reply.
788 @param ResultPtr The returned body of the reply.
790 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
791 the cause of failure.
796 IN CONST XENSTORE_TRANSACTION
*Transaction
,
797 IN
enum xsd_sockmsg_type RequestType
,
798 IN CONST WRITE_REQUEST
*WriteRequest
,
799 IN UINT32 NumRequests
,
800 OUT UINT32
*LenPtr OPTIONAL
,
801 OUT VOID
**ResultPtr OPTIONAL
804 struct xsd_sockmsg Message
;
807 XENSTORE_STATUS Status
;
809 if (Transaction
== XST_NIL
) {
812 Message
.tx_id
= Transaction
->Id
;
815 Message
.type
= RequestType
;
817 for (Index
= 0; Index
< NumRequests
; Index
++) {
818 Message
.len
+= WriteRequest
[Index
].Len
;
821 Status
= XenStoreWriteStore (&Message
, sizeof (Message
));
822 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
823 DEBUG ((EFI_D_ERROR
, "XenStoreTalkv failed %d\n", Status
));
827 for (Index
= 0; Index
< NumRequests
; Index
++) {
828 Status
= XenStoreWriteStore (WriteRequest
[Index
].Data
, WriteRequest
[Index
].Len
);
829 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
830 DEBUG ((EFI_D_ERROR
, "XenStoreTalkv failed %d\n", Status
));
835 Status
= XenStoreReadReply ((enum xsd_sockmsg_type
*)&Message
.type
, LenPtr
, &Return
);
838 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
842 if (Message
.type
== XS_ERROR
) {
843 Status
= XenStoreGetError (Return
);
848 /* Reply is either error or an echo of our request message type. */
849 ASSERT ((enum xsd_sockmsg_type
)Message
.type
== RequestType
);
857 return XENSTORE_STATUS_SUCCESS
;
861 Wrapper for XenStoreTalkv allowing easy transmission of a message with
862 a single, contiguous, message body.
864 The returned result is provided in malloced storage and thus must be free'd
867 @param Transaction The transaction to use for this request.
868 @param RequestType The type of message to send.
869 @param Body The body of the request.
870 @param LenPtr The returned length of the reply.
871 @param Result The returned body of the reply.
873 @return 0 on success. Otherwise an errno indicating
874 the cause of failure.
879 IN CONST XENSTORE_TRANSACTION
*Transaction
,
880 IN
enum xsd_sockmsg_type RequestType
,
881 IN CONST CHAR8
*Body
,
882 OUT UINT32
*LenPtr OPTIONAL
,
883 OUT VOID
**Result OPTIONAL
886 WRITE_REQUEST WriteRequest
;
888 WriteRequest
.Data
= (VOID
*) Body
;
889 WriteRequest
.Len
= (UINT32
)AsciiStrSize (Body
);
891 return XenStoreTalkv (Transaction
, RequestType
, &WriteRequest
, 1,
896 // XenStore Watch Support
900 Transmit a watch request to the XenStore service.
902 @param Path The path in the XenStore to watch.
903 @param Tocken A unique identifier for this watch.
905 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating the
915 WRITE_REQUEST WriteRequest
[2];
917 WriteRequest
[0].Data
= (VOID
*) Path
;
918 WriteRequest
[0].Len
= (UINT32
)AsciiStrSize (Path
);
919 WriteRequest
[1].Data
= (VOID
*) Token
;
920 WriteRequest
[1].Len
= (UINT32
)AsciiStrSize (Token
);
922 return XenStoreTalkv (XST_NIL
, XS_WATCH
, WriteRequest
, 2, NULL
, NULL
);
926 Transmit an uwatch request to the XenStore service.
928 @param Path The path in the XenStore to watch.
929 @param Tocken A unique identifier for this watch.
931 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
932 the cause of failure.
941 WRITE_REQUEST WriteRequest
[2];
943 WriteRequest
[0].Data
= (VOID
*) Path
;
944 WriteRequest
[0].Len
= (UINT32
)AsciiStrSize (Path
);
945 WriteRequest
[1].Data
= (VOID
*) Token
;
946 WriteRequest
[1].Len
= (UINT32
)AsciiStrSize (Token
);
948 return XenStoreTalkv (XST_NIL
, XS_UNWATCH
, WriteRequest
, 2, NULL
, NULL
);
957 XENSTORE_MESSAGE
*Message
;
958 LIST_ENTRY
*Entry
= NULL
;
959 LIST_ENTRY
*Last
= NULL
;
960 XENSTORE_STATUS Status
;
963 EfiAcquireLock (&xs
.WatchEventsLock
);
964 if (IsListEmpty (&xs
.WatchEvents
) ||
965 Last
== GetFirstNode (&xs
.WatchEvents
)) {
966 EfiReleaseLock (&xs
.WatchEventsLock
);
967 Status
= XenStoreProcessMessage ();
968 if (Status
!= XENSTORE_STATUS_SUCCESS
&& Status
!= XENSTORE_STATUS_EAGAIN
) {
974 for (Entry
= GetFirstNode (&xs
.WatchEvents
);
975 Entry
!= Last
&& !IsNull (&xs
.WatchEvents
, Entry
);
976 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
)) {
977 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
978 if (Message
->u
.Watch
.Handle
== Token
) {
979 RemoveEntryList (Entry
);
980 EfiReleaseLock (&xs
.WatchEventsLock
);
981 FreePool((VOID
*)Message
->u
.Watch
.Vector
);
983 return XENSTORE_STATUS_SUCCESS
;
986 Last
= GetFirstNode (&xs
.WatchEvents
);
987 EfiReleaseLock (&xs
.WatchEventsLock
);
993 NotifyEventChannelCheckForEvent (
998 XENSTORE_PRIVATE
*xsp
;
999 xsp
= (XENSTORE_PRIVATE
*)Context
;
1000 if (TestAndClearBit (xsp
->EventChannel
, xsp
->Dev
->SharedInfo
->evtchn_pending
)) {
1001 gBS
->SignalEvent (Event
);
1006 Setup communication channels with the XenStore service.
1008 @retval EFI_SUCCESS if everything went well.
1013 XENSTORE_PRIVATE
*xsp
1017 EFI_EVENT TimerEvent
;
1018 struct xenstore_domain_interface
*XenStore
= xsp
->XenStore
;
1020 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
1021 Status
= gBS
->SetTimer (TimerEvent
, TimerRelative
,
1022 EFI_TIMER_PERIOD_SECONDS (5));
1023 while (XenStore
->rsp_prod
!= XenStore
->rsp_cons
) {
1024 Status
= gBS
->CheckEvent (TimerEvent
);
1025 if (!EFI_ERROR (Status
)) {
1026 DEBUG ((EFI_D_WARN
, "XENSTORE response ring is not quiescent "
1027 "(%08x:%08x): fixing up\n",
1028 XenStore
->rsp_cons
, XenStore
->rsp_prod
));
1029 XenStore
->rsp_cons
= XenStore
->rsp_prod
;
1032 gBS
->CloseEvent (TimerEvent
);
1034 Status
= gBS
->CreateEvent (EVT_NOTIFY_WAIT
, TPL_NOTIFY
,
1035 NotifyEventChannelCheckForEvent
, xsp
,
1036 &xsp
->EventChannelEvent
);
1037 ASSERT_EFI_ERROR (Status
);
1043 Initialize XenStore.
1045 @param Dev A XENBUS_DEVICE instance.
1047 @retval EFI_SUCCESS if everything went well.
1056 * The HVM guest pseudo-physical frame number. This is Xen's mapping
1057 * of the true machine frame number into our "physical address space".
1063 xs
.EventChannel
= (evtchn_port_t
)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN
);
1064 XenStoreGpfn
= (UINTN
)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN
);
1065 xs
.XenStore
= (VOID
*) (XenStoreGpfn
<< EFI_PAGE_SHIFT
);
1066 DEBUG ((EFI_D_INFO
, "XenBusInit: XenBus rings @%p, event channel %x\n",
1067 xs
.XenStore
, xs
.EventChannel
));
1069 InitializeListHead (&xs
.ReplyList
);
1070 InitializeListHead (&xs
.WatchEvents
);
1071 InitializeListHead (&xs
.RegisteredWatches
);
1073 EfiInitializeLock (&xs
.ReplyLock
, TPL_NOTIFY
);
1074 EfiInitializeLock (&xs
.RegisteredWatchesLock
, TPL_NOTIFY
);
1075 EfiInitializeLock (&xs
.WatchEventsLock
, TPL_NOTIFY
);
1077 /* Initialize the shared memory rings to talk to xenstored */
1078 Status
= XenStoreInitComms (&xs
);
1079 if (EFI_ERROR (Status
)) {
1088 IN XENBUS_DEVICE
*Dev
1092 // Emptying the list RegisteredWatches, but this list should already be
1093 // empty. Every driver that is using Watches should unregister them when
1096 if (!IsListEmpty (&xs
.RegisteredWatches
)) {
1097 XENSTORE_WATCH
*Watch
;
1099 DEBUG ((EFI_D_WARN
, "XenStore: RegisteredWatches is not empty, cleaning up..."));
1100 Entry
= GetFirstNode (&xs
.RegisteredWatches
);
1101 while (!IsNull (&xs
.RegisteredWatches
, Entry
)) {
1102 Watch
= XENSTORE_WATCH_FROM_LINK (Entry
);
1103 Entry
= GetNextNode (&xs
.RegisteredWatches
, Entry
);
1105 XenStoreUnregisterWatch (Watch
);
1110 // Emptying the list WatchEvents, but this list should already be empty after
1111 // having cleanup the list RegisteredWatches.
1113 if (!IsListEmpty (&xs
.WatchEvents
)) {
1115 DEBUG ((EFI_D_WARN
, "XenStore: WatchEvents is not empty, cleaning up..."));
1116 Entry
= GetFirstNode (&xs
.WatchEvents
);
1117 while (!IsNull (&xs
.WatchEvents
, Entry
)) {
1118 XENSTORE_MESSAGE
*Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1119 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
);
1120 RemoveEntryList (&Message
->Link
);
1121 FreePool ((VOID
*)Message
->u
.Watch
.Vector
);
1126 if (!IsListEmpty (&xs
.ReplyList
)) {
1127 XENSTORE_MESSAGE
*Message
;
1129 Entry
= GetFirstNode (&xs
.ReplyList
);
1130 while (!IsNull (&xs
.ReplyList
, Entry
)) {
1131 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1132 Entry
= GetNextNode (&xs
.ReplyList
, Entry
);
1133 RemoveEntryList (&Message
->Link
);
1134 FreePool (Message
->u
.Reply
.Body
);
1139 gBS
->CloseEvent (xs
.EventChannelEvent
);
1141 if (xs
.XenStore
->server_features
& XENSTORE_SERVER_FEATURE_RECONNECTION
) {
1142 xs
.XenStore
->connection
= XENSTORE_RECONNECT
;
1143 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
1144 while (*(volatile UINT32
*)&xs
.XenStore
->connection
== XENSTORE_RECONNECT
) {
1145 XenStoreWaitForEvent (xs
.EventChannelEvent
, EFI_TIMER_PERIOD_MILLISECONDS (100));
1148 /* If the backend reads the state while we're erasing it then the
1149 * ring state will become corrupted, preventing guest frontends from
1150 * connecting. This is rare. To help diagnose the failure, we fill
1151 * the ring with XS_INVALID packets. */
1152 SetMem (xs
.XenStore
->req
, XENSTORE_RING_SIZE
, 0xff);
1153 SetMem (xs
.XenStore
->rsp
, XENSTORE_RING_SIZE
, 0xff);
1154 xs
.XenStore
->req_cons
= xs
.XenStore
->req_prod
= 0;
1155 xs
.XenStore
->rsp_cons
= xs
.XenStore
->rsp_prod
= 0;
1162 // API comments for these methods can be found in XenStore.h
1166 XenStoreListDirectory (
1167 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1168 IN CONST CHAR8
*DirectoryPath
,
1169 IN CONST CHAR8
*Node
,
1170 OUT UINT32
*DirectoryCountPtr
,
1171 OUT CONST CHAR8
***DirectoryListPtr
1177 XENSTORE_STATUS Status
;
1179 Path
= XenStoreJoin (DirectoryPath
, Node
);
1180 Status
= XenStoreSingle (Transaction
, XS_DIRECTORY
, Path
, &Len
,
1181 (VOID
**) &TempStr
);
1183 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1187 *DirectoryListPtr
= Split (TempStr
, Len
, DirectoryCountPtr
);
1189 return XENSTORE_STATUS_SUCCESS
;
1193 XenStorePathExists (
1194 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1195 IN CONST CHAR8
*Directory
,
1196 IN CONST CHAR8
*Node
1199 CONST CHAR8
**TempStr
;
1200 XENSTORE_STATUS Status
;
1203 Status
= XenStoreListDirectory (Transaction
, Directory
, Node
,
1204 &TempNum
, &TempStr
);
1205 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1208 FreePool ((VOID
*)TempStr
);
1214 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1215 IN CONST CHAR8
*DirectoryPath
,
1216 IN CONST CHAR8
*Node
,
1217 OUT UINT32
*LenPtr OPTIONAL
,
1223 XENSTORE_STATUS Status
;
1225 Path
= XenStoreJoin (DirectoryPath
, Node
);
1226 Status
= XenStoreSingle (Transaction
, XS_READ
, Path
, LenPtr
, &Value
);
1228 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1233 return XENSTORE_STATUS_SUCCESS
;
1238 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1239 IN CONST CHAR8
*DirectoryPath
,
1240 IN CONST CHAR8
*Node
,
1245 WRITE_REQUEST WriteRequest
[2];
1246 XENSTORE_STATUS Status
;
1248 Path
= XenStoreJoin (DirectoryPath
, Node
);
1250 WriteRequest
[0].Data
= (VOID
*) Path
;
1251 WriteRequest
[0].Len
= (UINT32
)AsciiStrSize (Path
);
1252 WriteRequest
[1].Data
= (VOID
*) Str
;
1253 WriteRequest
[1].Len
= (UINT32
)AsciiStrLen (Str
);
1255 Status
= XenStoreTalkv (Transaction
, XS_WRITE
, WriteRequest
, 2, NULL
, NULL
);
1263 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1264 IN CONST CHAR8
*DirectoryPath
,
1265 IN CONST CHAR8
*Node
1269 XENSTORE_STATUS Status
;
1271 Path
= XenStoreJoin (DirectoryPath
, Node
);
1272 Status
= XenStoreSingle (Transaction
, XS_RM
, Path
, NULL
, NULL
);
1279 XenStoreTransactionStart (
1280 OUT XENSTORE_TRANSACTION
*Transaction
1284 XENSTORE_STATUS Status
;
1286 Status
= XenStoreSingle (XST_NIL
, XS_TRANSACTION_START
, "", NULL
,
1288 if (Status
== XENSTORE_STATUS_SUCCESS
) {
1289 Transaction
->Id
= (UINT32
)AsciiStrDecimalToUintn (IdStr
);
1297 XenStoreTransactionEnd (
1298 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1304 AbortStr
[0] = Abort
? 'F' : 'T';
1307 return XenStoreSingle (Transaction
, XS_TRANSACTION_END
, AbortStr
, NULL
, NULL
);
1312 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1313 IN CONST CHAR8
*DirectoryPath
,
1314 IN CONST CHAR8
*Node
,
1315 IN CONST CHAR8
*FormatString
,
1320 XENSTORE_STATUS Status
;
1324 VA_COPY (Marker2
, Marker
);
1325 BufSize
= SPrintLengthAsciiFormat (FormatString
, Marker2
) + 1;
1327 Buf
= AllocateZeroPool (BufSize
);
1328 AsciiVSPrint (Buf
, BufSize
, FormatString
, Marker
);
1329 Status
= XenStoreWrite (Transaction
, DirectoryPath
, Node
, Buf
);
1338 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1339 IN CONST CHAR8
*DirectoryPath
,
1340 IN CONST CHAR8
*Node
,
1341 IN CONST CHAR8
*FormatString
,
1346 XENSTORE_STATUS Status
;
1348 VA_START (Marker
, FormatString
);
1349 Status
= XenStoreVSPrint (Transaction
, DirectoryPath
, Node
, FormatString
, Marker
);
1356 XenStoreRegisterWatch (
1357 IN CONST CHAR8
*DirectoryPath
,
1358 IN CONST CHAR8
*Node
,
1359 OUT XENSTORE_WATCH
**WatchPtr
1362 /* Pointer in ascii is the token. */
1363 CHAR8 Token
[sizeof (XENSTORE_WATCH
) * 2 + 1];
1364 XENSTORE_STATUS Status
;
1365 XENSTORE_WATCH
*Watch
;
1367 Watch
= AllocateZeroPool (sizeof (XENSTORE_WATCH
));
1368 Watch
->Signature
= XENSTORE_WATCH_SIGNATURE
;
1369 Watch
->Node
= XenStoreJoin (DirectoryPath
, Node
);
1371 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1372 InsertTailList (&xs
.RegisteredWatches
, &Watch
->Link
);
1373 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1375 AsciiSPrint (Token
, sizeof (Token
), "%p", (VOID
*) Watch
);
1376 Status
= XenStoreWatch (Watch
->Node
, Token
);
1378 /* Ignore errors due to multiple registration. */
1379 if (Status
== XENSTORE_STATUS_EEXIST
) {
1380 Status
= XENSTORE_STATUS_SUCCESS
;
1383 if (Status
== XENSTORE_STATUS_SUCCESS
) {
1386 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1387 RemoveEntryList (&Watch
->Link
);
1388 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1389 FreePool (Watch
->Node
);
1397 XenStoreUnregisterWatch (
1398 IN XENSTORE_WATCH
*Watch
1401 CHAR8 Token
[sizeof (Watch
) * 2 + 1];
1404 ASSERT (Watch
->Signature
== XENSTORE_WATCH_SIGNATURE
);
1406 AsciiSPrint (Token
, sizeof (Token
), "%p", (VOID
*) Watch
);
1407 if (XenStoreFindWatch (Token
) == NULL
) {
1411 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1412 RemoveEntryList (&Watch
->Link
);
1413 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1415 XenStoreUnwatch (Watch
->Node
, Token
);
1417 /* Cancel pending watch events. */
1418 EfiAcquireLock (&xs
.WatchEventsLock
);
1419 Entry
= GetFirstNode (&xs
.WatchEvents
);
1420 while (!IsNull (&xs
.WatchEvents
, Entry
)) {
1421 XENSTORE_MESSAGE
*Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1422 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
);
1423 if (Message
->u
.Watch
.Handle
== Watch
) {
1424 RemoveEntryList (&Message
->Link
);
1425 FreePool ((VOID
*)Message
->u
.Watch
.Vector
);
1429 EfiReleaseLock (&xs
.WatchEventsLock
);
1431 FreePool (Watch
->Node
);
1442 XenBusWaitForWatch (
1443 IN XENBUS_PROTOCOL
*This
,
1447 return XenStoreWaitWatch (Token
);
1452 XenBusXenStoreRead (
1453 IN XENBUS_PROTOCOL
*This
,
1454 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1455 IN CONST CHAR8
*Node
,
1459 return XenStoreRead (Transaction
, This
->Node
, Node
, NULL
, Value
);
1464 XenBusXenStoreBackendRead (
1465 IN XENBUS_PROTOCOL
*This
,
1466 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1467 IN CONST CHAR8
*Node
,
1471 return XenStoreRead (Transaction
, This
->Backend
, Node
, NULL
, Value
);
1476 XenBusXenStoreRemove (
1477 IN XENBUS_PROTOCOL
*This
,
1478 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1482 return XenStoreRemove (Transaction
, This
->Node
, Node
);
1487 XenBusXenStoreTransactionStart (
1488 IN XENBUS_PROTOCOL
*This
,
1489 OUT XENSTORE_TRANSACTION
*Transaction
1492 return XenStoreTransactionStart (Transaction
);
1497 XenBusXenStoreTransactionEnd (
1498 IN XENBUS_PROTOCOL
*This
,
1499 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1503 return XenStoreTransactionEnd (Transaction
, Abort
);
1508 XenBusXenStoreSPrint (
1509 IN XENBUS_PROTOCOL
*This
,
1510 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1511 IN CONST CHAR8
*DirectoryPath
,
1512 IN CONST CHAR8
*Node
,
1513 IN CONST CHAR8
*FormatString
,
1518 XENSTORE_STATUS Status
;
1520 VA_START (Marker
, FormatString
);
1521 Status
= XenStoreVSPrint (Transaction
, DirectoryPath
, Node
, FormatString
, Marker
);
1529 XenBusRegisterWatch (
1530 IN XENBUS_PROTOCOL
*This
,
1531 IN CONST CHAR8
*Node
,
1535 return XenStoreRegisterWatch (This
->Node
, Node
, (XENSTORE_WATCH
**) Token
);
1540 XenBusRegisterWatchBackend (
1541 IN XENBUS_PROTOCOL
*This
,
1542 IN CONST CHAR8
*Node
,
1546 return XenStoreRegisterWatch (This
->Backend
, Node
, (XENSTORE_WATCH
**) Token
);
1551 XenBusUnregisterWatch (
1552 IN XENBUS_PROTOCOL
*This
,
1556 XenStoreUnregisterWatch ((XENSTORE_WATCH
*) Token
);