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 SPDX-License-Identifier: MIT
43 #include <Library/PrintLib.h>
45 #include <IndustryStandard/Xen/hvm/params.h>
47 #include "EventChannel.h"
48 #include <Library/XenHypercallLib.h>
51 // Private Data Structures
59 /* Register callback to watch subtree (node) in the XenStore. */
60 #define XENSTORE_WATCH_SIGNATURE SIGNATURE_32 ('X','S','w','a')
61 struct _XENSTORE_WATCH
66 /* Path being watched. */
70 #define XENSTORE_WATCH_FROM_LINK(l) \
71 CR (l, XENSTORE_WATCH, Link, XENSTORE_WATCH_SIGNATURE)
75 * Structure capturing messages received from the XenStore service.
77 #define XENSTORE_MESSAGE_SIGNATURE SIGNATURE_32 ('X', 'S', 's', 'm')
82 struct xsd_sockmsg Header
;
90 /* Queued watch events. */
92 XENSTORE_WATCH
*Handle
;
98 #define XENSTORE_MESSAGE_FROM_LINK(r) \
99 CR (r, XENSTORE_MESSAGE, Link, XENSTORE_MESSAGE_SIGNATURE)
102 * Container for all XenStore related state.
106 * Pointer to shared memory communication structures allowing us
107 * to communicate with the XenStore service.
109 struct xenstore_domain_interface
*XenStore
;
114 * A list of replies to our requests.
116 * The reply list is filled by xs_rcv_thread(). It
117 * is consumed by the context that issued the request
118 * to which a reply is made. The requester blocks in
119 * XenStoreReadReply ().
121 * /note Only one requesting context can be active at a time.
123 LIST_ENTRY ReplyList
;
125 /** Lock protecting the reply list. */
129 * List of registered watches.
131 LIST_ENTRY RegisteredWatches
;
133 /** Lock protecting the registered watches list. */
134 EFI_LOCK RegisteredWatchesLock
;
137 * List of pending watch callback events.
139 LIST_ENTRY WatchEvents
;
141 /** Lock protecting the watch callback list. */
142 EFI_LOCK WatchEventsLock
;
145 * The event channel for communicating with the
148 evtchn_port_t EventChannel
;
150 /** Handle for XenStore events. */
151 EFI_EVENT EventChannelEvent
;
157 static XENSTORE_PRIVATE xs
;
161 // Private Utility Functions
165 Count and optionally record pointers to a number of NUL terminated
168 @param Strings A pointer to a contiguous buffer of NUL terminated strings.
169 @param Len The length of the buffer pointed to by strings.
170 @param Dst An array to store pointers to each string found in strings.
172 @return A count of the number of strings found.
177 IN CONST CHAR8
*Strings
,
179 OUT CONST CHAR8
**Dst OPTIONAL
185 for (Ptr
= Strings
; Ptr
< Strings
+ Len
; Ptr
+= AsciiStrSize (Ptr
)) {
196 Convert a contiguous buffer containing a series of NUL terminated
197 strings into an array of pointers to strings.
199 The returned pointer references the array of string pointers which
200 is followed by the storage for the string data. It is the client's
201 responsibility to free this storage.
203 The storage addressed by Strings is free'd prior to Split returning.
205 @param Strings A pointer to a contiguous buffer of NUL terminated strings.
206 @param Len The length of the buffer pointed to by strings.
207 @param NumPtr The number of strings found and returned in the strings
210 @return An array of pointers to the strings found in the input buffer.
222 ASSERT(NumPtr
!= NULL
);
223 ASSERT(Strings
!= NULL
);
225 /* Protect against unterminated buffers. */
227 Strings
[Len
- 1] = '\0';
230 /* Count the Strings. */
231 *NumPtr
= ExtractStrings (Strings
, Len
, NULL
);
233 /* Transfer to one big alloc for easy freeing by the caller. */
234 Dst
= AllocatePool (*NumPtr
* sizeof (CHAR8
*) + Len
);
235 CopyMem ((VOID
*)&Dst
[*NumPtr
], Strings
, Len
);
238 /* Extract pointers to newly allocated array. */
239 Strings
= (CHAR8
*) &Dst
[*NumPtr
];
240 ExtractStrings (Strings
, Len
, Dst
);
246 Convert from watch token (unique identifier) to the associated
247 internal tracking structure for this watch.
249 @param Tocken The unique identifier for the watch to find.
251 @return A pointer to the found watch structure or NULL.
256 IN CONST CHAR8
*Token
259 XENSTORE_WATCH
*Watch
, *WantedWatch
;
262 WantedWatch
= (VOID
*) AsciiStrHexToUintn (Token
);
264 if (IsListEmpty (&xs
.RegisteredWatches
)) {
267 for (Entry
= GetFirstNode (&xs
.RegisteredWatches
);
268 !IsNull (&xs
.RegisteredWatches
, Entry
);
269 Entry
= GetNextNode (&xs
.RegisteredWatches
, Entry
)) {
270 Watch
= XENSTORE_WATCH_FROM_LINK (Entry
);
271 if (Watch
== WantedWatch
)
279 // Public Utility Functions
280 // API comments for these methods can be found in XenStore.h
285 IN CONST CHAR8
*DirectoryPath
,
292 /* +1 for '/' and +1 for '\0' */
293 BufSize
= AsciiStrLen (DirectoryPath
) + AsciiStrLen (Node
) + 2;
294 Buf
= AllocatePool (BufSize
);
295 ASSERT (Buf
!= NULL
);
297 if (Node
[0] == '\0') {
298 AsciiSPrint (Buf
, BufSize
, "%a", DirectoryPath
);
300 AsciiSPrint (Buf
, BufSize
, "%a/%a", DirectoryPath
, Node
);
307 // Low Level Communication Management
311 Verify that the indexes for a ring are valid.
313 The difference between the producer and consumer cannot
314 exceed the size of the ring.
316 @param Cons The consumer index for the ring to test.
317 @param Prod The producer index for the ring to test.
319 @retval TRUE If indexes are in range.
320 @retval FALSE If the indexes are out of range.
324 XenStoreCheckIndexes (
325 XENSTORE_RING_IDX Cons
,
326 XENSTORE_RING_IDX Prod
329 return ((Prod
- Cons
) <= XENSTORE_RING_SIZE
);
333 Return a pointer to, and the length of, the contiguous
334 free region available for output in a ring buffer.
336 @param Cons The consumer index for the ring.
337 @param Prod The producer index for the ring.
338 @param Buffer The base address of the ring's storage.
339 @param LenPtr The amount of contiguous storage available.
341 @return A pointer to the start location of the free region.
345 XenStoreGetOutputChunk (
346 IN XENSTORE_RING_IDX Cons
,
347 IN XENSTORE_RING_IDX Prod
,
353 Len
= XENSTORE_RING_SIZE
- MASK_XENSTORE_IDX (Prod
);
354 if ((XENSTORE_RING_SIZE
- (Prod
- Cons
)) < Len
) {
355 Len
= XENSTORE_RING_SIZE
- (Prod
- Cons
);
358 return (Buffer
+ MASK_XENSTORE_IDX (Prod
));
362 Return a pointer to, and the length of, the contiguous
363 data available to read from a ring buffer.
365 @param Cons The consumer index for the ring.
366 @param Prod The producer index for the ring.
367 @param Buffer The base address of the ring's storage.
368 @param LenPtr The amount of contiguous data available to read.
370 @return A pointer to the start location of the available data.
374 XenStoreGetInputChunk (
375 IN XENSTORE_RING_IDX Cons
,
376 IN XENSTORE_RING_IDX Prod
,
377 IN CONST CHAR8
*Buffer
,
383 Len
= XENSTORE_RING_SIZE
- MASK_XENSTORE_IDX (Cons
);
384 if ((Prod
- Cons
) < Len
) {
388 return (Buffer
+ MASK_XENSTORE_IDX (Cons
));
392 Wait for an event or timeout.
394 @param Event Event to wait for.
395 @param Timeout A timeout value in 100ns units.
397 @retval EFI_SUCCESS Event have been triggered or the current TPL is not
399 @retval EFI_TIMEOUT Timeout have expired.
403 XenStoreWaitForEvent (
410 EFI_EVENT TimerEvent
;
411 EFI_EVENT WaitList
[2];
413 gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
414 gBS
->SetTimer (TimerEvent
, TimerRelative
, Timeout
);
416 WaitList
[0] = xs
.EventChannelEvent
;
417 WaitList
[1] = TimerEvent
;
418 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
419 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
420 gBS
->CloseEvent (TimerEvent
);
421 if (Status
== EFI_UNSUPPORTED
) {
432 Transmit data to the XenStore service.
434 The buffer pointed to by DataPtr is at least Len bytes in length.
436 @param DataPtr A pointer to the contiguous data to send.
437 @param Len The amount of data to send.
439 @return On success 0, otherwise an errno value indicating the
445 IN CONST VOID
*DataPtr
,
449 XENSTORE_RING_IDX Cons
, Prod
;
450 CONST CHAR8
*Data
= (CONST CHAR8
*)DataPtr
;
456 Cons
= xs
.XenStore
->req_cons
;
457 Prod
= xs
.XenStore
->req_prod
;
458 if ((Prod
- Cons
) == XENSTORE_RING_SIZE
) {
460 * Output ring is full. Wait for a ring event.
462 * Note that the events from both queues are combined, so being woken
463 * does not guarantee that data exist in the read ring.
467 Status
= XenStoreWaitForEvent (xs
.EventChannelEvent
,
468 EFI_TIMER_PERIOD_SECONDS (1));
469 if (Status
== EFI_TIMEOUT
) {
470 DEBUG ((DEBUG_WARN
, "XenStore Write, waiting for a ring event.\n"));
475 /* Verify queue sanity. */
476 if (!XenStoreCheckIndexes (Cons
, Prod
)) {
477 xs
.XenStore
->req_cons
= xs
.XenStore
->req_prod
= 0;
478 return XENSTORE_STATUS_EIO
;
481 Dest
= XenStoreGetOutputChunk (Cons
, Prod
, xs
.XenStore
->req
, &Available
);
482 if (Available
> Len
) {
486 CopyMem (Dest
, Data
, Available
);
491 * The store to the producer index, which indicates
492 * to the other side that new data has arrived, must
493 * be visible only after our copy of the data into the
494 * ring has completed.
497 xs
.XenStore
->req_prod
+= Available
;
500 * The other side will see the change to req_prod at the time of the
504 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
507 return XENSTORE_STATUS_SUCCESS
;
511 Receive data from the XenStore service.
513 The buffer pointed to by DataPtr is at least Len bytes in length.
515 @param DataPtr A pointer to the contiguous buffer to receive the data.
516 @param Len The amount of data to receive.
518 @return On success 0, otherwise an errno value indicating the
528 XENSTORE_RING_IDX Cons
, Prod
;
529 CHAR8
*Data
= (CHAR8
*) DataPtr
;
535 Cons
= xs
.XenStore
->rsp_cons
;
536 Prod
= xs
.XenStore
->rsp_prod
;
539 * Nothing to read. Wait for a ring event.
541 * Note that the events from both queues are combined, so being woken
542 * does not guarantee that data exist in the read ring.
546 Status
= XenStoreWaitForEvent (xs
.EventChannelEvent
,
547 EFI_TIMER_PERIOD_SECONDS (1));
548 if (Status
== EFI_TIMEOUT
) {
549 DEBUG ((DEBUG_WARN
, "XenStore Read, waiting for a ring event.\n"));
554 /* Verify queue sanity. */
555 if (!XenStoreCheckIndexes (Cons
, Prod
)) {
556 xs
.XenStore
->rsp_cons
= xs
.XenStore
->rsp_prod
= 0;
557 return XENSTORE_STATUS_EIO
;
560 Src
= XenStoreGetInputChunk (Cons
, Prod
, xs
.XenStore
->rsp
, &Available
);
561 if (Available
> Len
) {
566 * Insure the data we read is related to the indexes
571 CopyMem (Data
, Src
, Available
);
576 * Insure that the producer of this ring does not see
577 * the ring space as free until after we have copied it
581 xs
.XenStore
->rsp_cons
+= Available
;
584 * The producer will see the updated consumer index when the event is
588 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
591 return XENSTORE_STATUS_SUCCESS
;
595 // Received Message Processing
599 Block reading the next message from the XenStore service and
602 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno value
603 indicating the type of failure encountered.
607 XenStoreProcessMessage (
611 XENSTORE_MESSAGE
*Message
;
613 XENSTORE_STATUS Status
;
615 Message
= AllocateZeroPool (sizeof (XENSTORE_MESSAGE
));
616 Message
->Signature
= XENSTORE_MESSAGE_SIGNATURE
;
617 Status
= XenStoreReadStore (&Message
->Header
, sizeof (Message
->Header
));
618 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
620 DEBUG ((DEBUG_ERROR
, "XenStore: Error read store (%d)\n", Status
));
624 Body
= AllocatePool (Message
->Header
.len
+ 1);
625 Status
= XenStoreReadStore (Body
, Message
->Header
.len
);
626 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
629 DEBUG ((DEBUG_ERROR
, "XenStore: Error read store (%d)\n", Status
));
632 Body
[Message
->Header
.len
] = '\0';
634 if (Message
->Header
.type
== XS_WATCH_EVENT
) {
635 Message
->u
.Watch
.Vector
= Split(Body
, Message
->Header
.len
,
636 &Message
->u
.Watch
.VectorSize
);
638 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
639 Message
->u
.Watch
.Handle
=
640 XenStoreFindWatch (Message
->u
.Watch
.Vector
[XS_WATCH_TOKEN
]);
641 DEBUG ((DEBUG_INFO
, "XenStore: Watch event %a\n",
642 Message
->u
.Watch
.Vector
[XS_WATCH_TOKEN
]));
643 if (Message
->u
.Watch
.Handle
!= NULL
) {
644 EfiAcquireLock (&xs
.WatchEventsLock
);
645 InsertHeadList (&xs
.WatchEvents
, &Message
->Link
);
646 EfiReleaseLock (&xs
.WatchEventsLock
);
648 DEBUG ((DEBUG_WARN
, "XenStore: Watch handle %a not found\n",
649 Message
->u
.Watch
.Vector
[XS_WATCH_TOKEN
]));
650 FreePool((VOID
*)Message
->u
.Watch
.Vector
);
653 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
655 Message
->u
.Reply
.Body
= Body
;
656 EfiAcquireLock (&xs
.ReplyLock
);
657 InsertTailList (&xs
.ReplyList
, &Message
->Link
);
658 EfiReleaseLock (&xs
.ReplyLock
);
661 return XENSTORE_STATUS_SUCCESS
;
665 // XenStore Message Request/Reply Processing
669 Convert a XenStore error string into an errno number.
671 Unknown error strings are converted to EINVAL.
673 @param errorstring The error string to convert.
675 @return The errno best matching the input string.
679 XENSTORE_STATUS Status
;
680 CONST CHAR8
*ErrorStr
;
683 static XenStoreErrors gXenStoreErrors
[] = {
684 { XENSTORE_STATUS_EINVAL
, "EINVAL" },
685 { XENSTORE_STATUS_EACCES
, "EACCES" },
686 { XENSTORE_STATUS_EEXIST
, "EEXIST" },
687 { XENSTORE_STATUS_EISDIR
, "EISDIR" },
688 { XENSTORE_STATUS_ENOENT
, "ENOENT" },
689 { XENSTORE_STATUS_ENOMEM
, "ENOMEM" },
690 { XENSTORE_STATUS_ENOSPC
, "ENOSPC" },
691 { XENSTORE_STATUS_EIO
, "EIO" },
692 { XENSTORE_STATUS_ENOTEMPTY
, "ENOTEMPTY" },
693 { XENSTORE_STATUS_ENOSYS
, "ENOSYS" },
694 { XENSTORE_STATUS_EROFS
, "EROFS" },
695 { XENSTORE_STATUS_EBUSY
, "EBUSY" },
696 { XENSTORE_STATUS_EAGAIN
, "EAGAIN" },
697 { XENSTORE_STATUS_EISCONN
, "EISCONN" },
698 { XENSTORE_STATUS_E2BIG
, "E2BIG" }
704 CONST CHAR8
*ErrorStr
709 for (Index
= 0; Index
< ARRAY_SIZE(gXenStoreErrors
); Index
++) {
710 if (!AsciiStrCmp (ErrorStr
, gXenStoreErrors
[Index
].ErrorStr
)) {
711 return gXenStoreErrors
[Index
].Status
;
714 DEBUG ((DEBUG_WARN
, "XenStore gave unknown error %a\n", ErrorStr
));
715 return XENSTORE_STATUS_EINVAL
;
719 Block waiting for a reply to a message request.
721 @param TypePtr The returned type of the reply.
722 @param LenPtr The returned body length of the reply.
723 @param Result The returned body of the reply.
728 OUT
enum xsd_sockmsg_type
*TypePtr
,
729 OUT UINT32
*LenPtr OPTIONAL
,
733 XENSTORE_MESSAGE
*Message
;
737 while (IsListEmpty (&xs
.ReplyList
)) {
738 XENSTORE_STATUS Status
;
739 Status
= XenStoreProcessMessage ();
740 if (Status
!= XENSTORE_STATUS_SUCCESS
&& Status
!= XENSTORE_STATUS_EAGAIN
) {
741 DEBUG ((DEBUG_ERROR
, "XenStore, error while reading the ring (%d).",
746 EfiAcquireLock (&xs
.ReplyLock
);
747 Entry
= GetFirstNode (&xs
.ReplyList
);
748 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
749 RemoveEntryList (Entry
);
750 EfiReleaseLock (&xs
.ReplyLock
);
752 *TypePtr
= Message
->Header
.type
;
753 if (LenPtr
!= NULL
) {
754 *LenPtr
= Message
->Header
.len
;
756 Body
= Message
->u
.Reply
.Body
;
760 return XENSTORE_STATUS_SUCCESS
;
764 Send a message with an optionally multi-part body to the XenStore service.
766 @param Transaction The transaction to use for this request.
767 @param RequestType The type of message to send.
768 @param WriteRequest Pointers to the body sections of the request.
769 @param NumRequests The number of body sections in the request.
770 @param LenPtr The returned length of the reply.
771 @param ResultPtr The returned body of the reply.
773 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
774 the cause of failure.
779 IN CONST XENSTORE_TRANSACTION
*Transaction
,
780 IN
enum xsd_sockmsg_type RequestType
,
781 IN CONST WRITE_REQUEST
*WriteRequest
,
782 IN UINT32 NumRequests
,
783 OUT UINT32
*LenPtr OPTIONAL
,
784 OUT VOID
**ResultPtr OPTIONAL
787 struct xsd_sockmsg Message
;
790 XENSTORE_STATUS Status
;
792 if (Transaction
== XST_NIL
) {
795 Message
.tx_id
= Transaction
->Id
;
798 Message
.type
= RequestType
;
800 for (Index
= 0; Index
< NumRequests
; Index
++) {
801 Message
.len
+= WriteRequest
[Index
].Len
;
804 Status
= XenStoreWriteStore (&Message
, sizeof (Message
));
805 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
806 DEBUG ((DEBUG_ERROR
, "XenStoreTalkv failed %d\n", Status
));
810 for (Index
= 0; Index
< NumRequests
; Index
++) {
811 Status
= XenStoreWriteStore (WriteRequest
[Index
].Data
, WriteRequest
[Index
].Len
);
812 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
813 DEBUG ((DEBUG_ERROR
, "XenStoreTalkv failed %d\n", Status
));
818 Status
= XenStoreReadReply ((enum xsd_sockmsg_type
*)&Message
.type
, LenPtr
, &Return
);
821 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
825 if (Message
.type
== XS_ERROR
) {
826 Status
= XenStoreGetError (Return
);
831 /* Reply is either error or an echo of our request message type. */
832 ASSERT ((enum xsd_sockmsg_type
)Message
.type
== RequestType
);
840 return XENSTORE_STATUS_SUCCESS
;
844 Wrapper for XenStoreTalkv allowing easy transmission of a message with
845 a single, contiguous, message body.
847 The returned result is provided in malloced storage and thus must be free'd
850 @param Transaction The transaction to use for this request.
851 @param RequestType The type of message to send.
852 @param Body The body of the request.
853 @param LenPtr The returned length of the reply.
854 @param Result The returned body of the reply.
856 @return 0 on success. Otherwise an errno indicating
857 the cause of failure.
862 IN CONST XENSTORE_TRANSACTION
*Transaction
,
863 IN
enum xsd_sockmsg_type RequestType
,
864 IN CONST CHAR8
*Body
,
865 OUT UINT32
*LenPtr OPTIONAL
,
866 OUT VOID
**Result OPTIONAL
869 WRITE_REQUEST WriteRequest
;
871 WriteRequest
.Data
= (VOID
*) Body
;
872 WriteRequest
.Len
= (UINT32
)AsciiStrSize (Body
);
874 return XenStoreTalkv (Transaction
, RequestType
, &WriteRequest
, 1,
879 // XenStore Watch Support
883 Transmit a watch request to the XenStore service.
885 @param Path The path in the XenStore to watch.
886 @param Tocken A unique identifier for this watch.
888 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating the
898 WRITE_REQUEST WriteRequest
[2];
900 WriteRequest
[0].Data
= (VOID
*) Path
;
901 WriteRequest
[0].Len
= (UINT32
)AsciiStrSize (Path
);
902 WriteRequest
[1].Data
= (VOID
*) Token
;
903 WriteRequest
[1].Len
= (UINT32
)AsciiStrSize (Token
);
905 return XenStoreTalkv (XST_NIL
, XS_WATCH
, WriteRequest
, 2, NULL
, NULL
);
909 Transmit an uwatch request to the XenStore service.
911 @param Path The path in the XenStore to watch.
912 @param Tocken A unique identifier for this watch.
914 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
915 the cause of failure.
924 WRITE_REQUEST WriteRequest
[2];
926 WriteRequest
[0].Data
= (VOID
*) Path
;
927 WriteRequest
[0].Len
= (UINT32
)AsciiStrSize (Path
);
928 WriteRequest
[1].Data
= (VOID
*) Token
;
929 WriteRequest
[1].Len
= (UINT32
)AsciiStrSize (Token
);
931 return XenStoreTalkv (XST_NIL
, XS_UNWATCH
, WriteRequest
, 2, NULL
, NULL
);
940 XENSTORE_MESSAGE
*Message
;
941 LIST_ENTRY
*Entry
= NULL
;
942 LIST_ENTRY
*Last
= NULL
;
943 XENSTORE_STATUS Status
;
946 EfiAcquireLock (&xs
.WatchEventsLock
);
947 if (IsListEmpty (&xs
.WatchEvents
) ||
948 Last
== GetFirstNode (&xs
.WatchEvents
)) {
949 EfiReleaseLock (&xs
.WatchEventsLock
);
950 Status
= XenStoreProcessMessage ();
951 if (Status
!= XENSTORE_STATUS_SUCCESS
&& Status
!= XENSTORE_STATUS_EAGAIN
) {
957 for (Entry
= GetFirstNode (&xs
.WatchEvents
);
958 Entry
!= Last
&& !IsNull (&xs
.WatchEvents
, Entry
);
959 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
)) {
960 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
961 if (Message
->u
.Watch
.Handle
== Token
) {
962 RemoveEntryList (Entry
);
963 EfiReleaseLock (&xs
.WatchEventsLock
);
964 FreePool((VOID
*)Message
->u
.Watch
.Vector
);
966 return XENSTORE_STATUS_SUCCESS
;
969 Last
= GetFirstNode (&xs
.WatchEvents
);
970 EfiReleaseLock (&xs
.WatchEventsLock
);
976 NotifyEventChannelCheckForEvent (
981 XENSTORE_PRIVATE
*xsp
;
982 xsp
= (XENSTORE_PRIVATE
*)Context
;
983 if (TestAndClearBit (xsp
->EventChannel
, xsp
->Dev
->SharedInfo
->evtchn_pending
)) {
984 gBS
->SignalEvent (Event
);
989 Setup communication channels with the XenStore service.
991 @retval EFI_SUCCESS if everything went well.
996 XENSTORE_PRIVATE
*xsp
1000 EFI_EVENT TimerEvent
;
1001 struct xenstore_domain_interface
*XenStore
= xsp
->XenStore
;
1003 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
1004 Status
= gBS
->SetTimer (TimerEvent
, TimerRelative
,
1005 EFI_TIMER_PERIOD_SECONDS (5));
1006 while (XenStore
->rsp_prod
!= XenStore
->rsp_cons
) {
1007 Status
= gBS
->CheckEvent (TimerEvent
);
1008 if (!EFI_ERROR (Status
)) {
1009 DEBUG ((DEBUG_WARN
, "XENSTORE response ring is not quiescent "
1010 "(%08x:%08x): fixing up\n",
1011 XenStore
->rsp_cons
, XenStore
->rsp_prod
));
1012 XenStore
->rsp_cons
= XenStore
->rsp_prod
;
1015 gBS
->CloseEvent (TimerEvent
);
1017 Status
= gBS
->CreateEvent (EVT_NOTIFY_WAIT
, TPL_NOTIFY
,
1018 NotifyEventChannelCheckForEvent
, xsp
,
1019 &xsp
->EventChannelEvent
);
1020 ASSERT_EFI_ERROR (Status
);
1026 Initialize XenStore.
1028 @param Dev A XENBUS_DEVICE instance.
1030 @retval EFI_SUCCESS if everything went well.
1039 * The HVM guest pseudo-physical frame number. This is Xen's mapping
1040 * of the true machine frame number into our "physical address space".
1046 xs
.EventChannel
= (evtchn_port_t
)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN
);
1047 XenStoreGpfn
= (UINTN
)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN
);
1048 xs
.XenStore
= (VOID
*) (XenStoreGpfn
<< EFI_PAGE_SHIFT
);
1049 DEBUG ((DEBUG_INFO
, "XenBusInit: XenBus rings @%p, event channel %x\n",
1050 xs
.XenStore
, xs
.EventChannel
));
1052 InitializeListHead (&xs
.ReplyList
);
1053 InitializeListHead (&xs
.WatchEvents
);
1054 InitializeListHead (&xs
.RegisteredWatches
);
1056 EfiInitializeLock (&xs
.ReplyLock
, TPL_NOTIFY
);
1057 EfiInitializeLock (&xs
.RegisteredWatchesLock
, TPL_NOTIFY
);
1058 EfiInitializeLock (&xs
.WatchEventsLock
, TPL_NOTIFY
);
1060 /* Initialize the shared memory rings to talk to xenstored */
1061 Status
= XenStoreInitComms (&xs
);
1068 IN XENBUS_DEVICE
*Dev
1072 // Emptying the list RegisteredWatches, but this list should already be
1073 // empty. Every driver that is using Watches should unregister them when
1076 if (!IsListEmpty (&xs
.RegisteredWatches
)) {
1077 XENSTORE_WATCH
*Watch
;
1079 DEBUG ((DEBUG_WARN
, "XenStore: RegisteredWatches is not empty, cleaning up..."));
1080 Entry
= GetFirstNode (&xs
.RegisteredWatches
);
1081 while (!IsNull (&xs
.RegisteredWatches
, Entry
)) {
1082 Watch
= XENSTORE_WATCH_FROM_LINK (Entry
);
1083 Entry
= GetNextNode (&xs
.RegisteredWatches
, Entry
);
1085 XenStoreUnregisterWatch (Watch
);
1090 // Emptying the list WatchEvents, but this list should already be empty after
1091 // having cleanup the list RegisteredWatches.
1093 if (!IsListEmpty (&xs
.WatchEvents
)) {
1095 DEBUG ((DEBUG_WARN
, "XenStore: WatchEvents is not empty, cleaning up..."));
1096 Entry
= GetFirstNode (&xs
.WatchEvents
);
1097 while (!IsNull (&xs
.WatchEvents
, Entry
)) {
1098 XENSTORE_MESSAGE
*Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1099 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
);
1100 RemoveEntryList (&Message
->Link
);
1101 FreePool ((VOID
*)Message
->u
.Watch
.Vector
);
1106 if (!IsListEmpty (&xs
.ReplyList
)) {
1107 XENSTORE_MESSAGE
*Message
;
1109 Entry
= GetFirstNode (&xs
.ReplyList
);
1110 while (!IsNull (&xs
.ReplyList
, Entry
)) {
1111 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1112 Entry
= GetNextNode (&xs
.ReplyList
, Entry
);
1113 RemoveEntryList (&Message
->Link
);
1114 FreePool (Message
->u
.Reply
.Body
);
1119 gBS
->CloseEvent (xs
.EventChannelEvent
);
1121 if (xs
.XenStore
->server_features
& XENSTORE_SERVER_FEATURE_RECONNECTION
) {
1122 xs
.XenStore
->connection
= XENSTORE_RECONNECT
;
1123 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
1124 while (*(volatile UINT32
*)&xs
.XenStore
->connection
== XENSTORE_RECONNECT
) {
1125 XenStoreWaitForEvent (xs
.EventChannelEvent
, EFI_TIMER_PERIOD_MILLISECONDS (100));
1128 /* If the backend reads the state while we're erasing it then the
1129 * ring state will become corrupted, preventing guest frontends from
1130 * connecting. This is rare. To help diagnose the failure, we fill
1131 * the ring with XS_INVALID packets. */
1132 SetMem (xs
.XenStore
->req
, XENSTORE_RING_SIZE
, 0xff);
1133 SetMem (xs
.XenStore
->rsp
, XENSTORE_RING_SIZE
, 0xff);
1134 xs
.XenStore
->req_cons
= xs
.XenStore
->req_prod
= 0;
1135 xs
.XenStore
->rsp_cons
= xs
.XenStore
->rsp_prod
= 0;
1142 // API comments for these methods can be found in XenStore.h
1146 XenStoreListDirectory (
1147 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1148 IN CONST CHAR8
*DirectoryPath
,
1149 IN CONST CHAR8
*Node
,
1150 OUT UINT32
*DirectoryCountPtr
,
1151 OUT CONST CHAR8
***DirectoryListPtr
1157 XENSTORE_STATUS Status
;
1159 Path
= XenStoreJoin (DirectoryPath
, Node
);
1160 Status
= XenStoreSingle (Transaction
, XS_DIRECTORY
, Path
, &Len
,
1161 (VOID
**) &TempStr
);
1163 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1167 *DirectoryListPtr
= Split (TempStr
, Len
, DirectoryCountPtr
);
1169 return XENSTORE_STATUS_SUCCESS
;
1173 XenStorePathExists (
1174 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1175 IN CONST CHAR8
*Directory
,
1176 IN CONST CHAR8
*Node
1179 CONST CHAR8
**TempStr
;
1180 XENSTORE_STATUS Status
;
1183 Status
= XenStoreListDirectory (Transaction
, Directory
, Node
,
1184 &TempNum
, &TempStr
);
1185 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1188 FreePool ((VOID
*)TempStr
);
1194 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1195 IN CONST CHAR8
*DirectoryPath
,
1196 IN CONST CHAR8
*Node
,
1197 OUT UINT32
*LenPtr OPTIONAL
,
1203 XENSTORE_STATUS Status
;
1205 Path
= XenStoreJoin (DirectoryPath
, Node
);
1206 Status
= XenStoreSingle (Transaction
, XS_READ
, Path
, LenPtr
, &Value
);
1208 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1213 return XENSTORE_STATUS_SUCCESS
;
1218 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1219 IN CONST CHAR8
*DirectoryPath
,
1220 IN CONST CHAR8
*Node
,
1225 WRITE_REQUEST WriteRequest
[2];
1226 XENSTORE_STATUS Status
;
1228 Path
= XenStoreJoin (DirectoryPath
, Node
);
1230 WriteRequest
[0].Data
= (VOID
*) Path
;
1231 WriteRequest
[0].Len
= (UINT32
)AsciiStrSize (Path
);
1232 WriteRequest
[1].Data
= (VOID
*) Str
;
1233 WriteRequest
[1].Len
= (UINT32
)AsciiStrLen (Str
);
1235 Status
= XenStoreTalkv (Transaction
, XS_WRITE
, WriteRequest
, 2, NULL
, NULL
);
1243 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1244 IN CONST CHAR8
*DirectoryPath
,
1245 IN CONST CHAR8
*Node
1249 XENSTORE_STATUS Status
;
1251 Path
= XenStoreJoin (DirectoryPath
, Node
);
1252 Status
= XenStoreSingle (Transaction
, XS_RM
, Path
, NULL
, NULL
);
1259 XenStoreTransactionStart (
1260 OUT XENSTORE_TRANSACTION
*Transaction
1264 XENSTORE_STATUS Status
;
1266 Status
= XenStoreSingle (XST_NIL
, XS_TRANSACTION_START
, "", NULL
,
1268 if (Status
== XENSTORE_STATUS_SUCCESS
) {
1269 Transaction
->Id
= (UINT32
)AsciiStrDecimalToUintn (IdStr
);
1277 XenStoreTransactionEnd (
1278 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1284 AbortStr
[0] = Abort
? 'F' : 'T';
1287 return XenStoreSingle (Transaction
, XS_TRANSACTION_END
, AbortStr
, NULL
, NULL
);
1293 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1294 IN CONST CHAR8
*DirectoryPath
,
1295 IN CONST CHAR8
*Node
,
1296 IN CONST CHAR8
*FormatString
,
1301 XENSTORE_STATUS Status
;
1305 VA_COPY (Marker2
, Marker
);
1306 BufSize
= SPrintLengthAsciiFormat (FormatString
, Marker2
) + 1;
1308 Buf
= AllocateZeroPool (BufSize
);
1309 AsciiVSPrint (Buf
, BufSize
, FormatString
, Marker
);
1310 Status
= XenStoreWrite (Transaction
, DirectoryPath
, Node
, Buf
);
1319 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1320 IN CONST CHAR8
*DirectoryPath
,
1321 IN CONST CHAR8
*Node
,
1322 IN CONST CHAR8
*FormatString
,
1327 XENSTORE_STATUS Status
;
1329 VA_START (Marker
, FormatString
);
1330 Status
= XenStoreVSPrint (Transaction
, DirectoryPath
, Node
, FormatString
, Marker
);
1337 XenStoreRegisterWatch (
1338 IN CONST CHAR8
*DirectoryPath
,
1339 IN CONST CHAR8
*Node
,
1340 OUT XENSTORE_WATCH
**WatchPtr
1343 /* Pointer in ascii is the token. */
1344 CHAR8 Token
[sizeof (XENSTORE_WATCH
) * 2 + 1];
1345 XENSTORE_STATUS Status
;
1346 XENSTORE_WATCH
*Watch
;
1348 Watch
= AllocateZeroPool (sizeof (XENSTORE_WATCH
));
1349 Watch
->Signature
= XENSTORE_WATCH_SIGNATURE
;
1350 Watch
->Node
= XenStoreJoin (DirectoryPath
, Node
);
1352 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1353 InsertTailList (&xs
.RegisteredWatches
, &Watch
->Link
);
1354 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1356 AsciiSPrint (Token
, sizeof (Token
), "%p", (VOID
*) Watch
);
1357 Status
= XenStoreWatch (Watch
->Node
, Token
);
1359 /* Ignore errors due to multiple registration. */
1360 if (Status
== XENSTORE_STATUS_EEXIST
) {
1361 Status
= XENSTORE_STATUS_SUCCESS
;
1364 if (Status
== XENSTORE_STATUS_SUCCESS
) {
1367 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1368 RemoveEntryList (&Watch
->Link
);
1369 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1370 FreePool (Watch
->Node
);
1378 XenStoreUnregisterWatch (
1379 IN XENSTORE_WATCH
*Watch
1382 CHAR8 Token
[sizeof (Watch
) * 2 + 1];
1385 ASSERT (Watch
->Signature
== XENSTORE_WATCH_SIGNATURE
);
1387 AsciiSPrint (Token
, sizeof (Token
), "%p", (VOID
*) Watch
);
1388 if (XenStoreFindWatch (Token
) == NULL
) {
1392 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1393 RemoveEntryList (&Watch
->Link
);
1394 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1396 XenStoreUnwatch (Watch
->Node
, Token
);
1398 /* Cancel pending watch events. */
1399 EfiAcquireLock (&xs
.WatchEventsLock
);
1400 Entry
= GetFirstNode (&xs
.WatchEvents
);
1401 while (!IsNull (&xs
.WatchEvents
, Entry
)) {
1402 XENSTORE_MESSAGE
*Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1403 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
);
1404 if (Message
->u
.Watch
.Handle
== Watch
) {
1405 RemoveEntryList (&Message
->Link
);
1406 FreePool ((VOID
*)Message
->u
.Watch
.Vector
);
1410 EfiReleaseLock (&xs
.WatchEventsLock
);
1412 FreePool (Watch
->Node
);
1423 XenBusWaitForWatch (
1424 IN XENBUS_PROTOCOL
*This
,
1428 return XenStoreWaitWatch (Token
);
1433 XenBusXenStoreRead (
1434 IN XENBUS_PROTOCOL
*This
,
1435 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1436 IN CONST CHAR8
*Node
,
1440 return XenStoreRead (Transaction
, This
->Node
, Node
, NULL
, Value
);
1445 XenBusXenStoreBackendRead (
1446 IN XENBUS_PROTOCOL
*This
,
1447 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1448 IN CONST CHAR8
*Node
,
1452 return XenStoreRead (Transaction
, This
->Backend
, Node
, NULL
, Value
);
1457 XenBusXenStoreRemove (
1458 IN XENBUS_PROTOCOL
*This
,
1459 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1463 return XenStoreRemove (Transaction
, This
->Node
, Node
);
1468 XenBusXenStoreTransactionStart (
1469 IN XENBUS_PROTOCOL
*This
,
1470 OUT XENSTORE_TRANSACTION
*Transaction
1473 return XenStoreTransactionStart (Transaction
);
1478 XenBusXenStoreTransactionEnd (
1479 IN XENBUS_PROTOCOL
*This
,
1480 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1484 return XenStoreTransactionEnd (Transaction
, Abort
);
1489 XenBusXenStoreSPrint (
1490 IN XENBUS_PROTOCOL
*This
,
1491 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1492 IN CONST CHAR8
*DirectoryPath
,
1493 IN CONST CHAR8
*Node
,
1494 IN CONST CHAR8
*FormatString
,
1499 XENSTORE_STATUS Status
;
1501 VA_START (Marker
, FormatString
);
1502 Status
= XenStoreVSPrint (Transaction
, DirectoryPath
, Node
, FormatString
, Marker
);
1510 XenBusRegisterWatch (
1511 IN XENBUS_PROTOCOL
*This
,
1512 IN CONST CHAR8
*Node
,
1516 return XenStoreRegisterWatch (This
->Node
, Node
, (XENSTORE_WATCH
**) Token
);
1521 XenBusRegisterWatchBackend (
1522 IN XENBUS_PROTOCOL
*This
,
1523 IN CONST CHAR8
*Node
,
1527 return XenStoreRegisterWatch (This
->Backend
, Node
, (XENSTORE_WATCH
**) Token
);
1532 XenBusUnregisterWatch (
1533 IN XENBUS_PROTOCOL
*This
,
1537 XenStoreUnregisterWatch ((XENSTORE_WATCH
*) Token
);