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 hierachy
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 "XenHypercall.h"
64 #include "EventChannel.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 (&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
,
307 /* +1 for '/' and +1 for '\0' */
308 Buf
= AllocateZeroPool (
309 AsciiStrLen (DirectoryPath
) + AsciiStrLen (Node
) + 2);
310 AsciiStrCat (Buf
, DirectoryPath
);
311 if (Node
[0] != '\0') {
312 AsciiStrCat (Buf
, "/");
313 AsciiStrCat (Buf
, Node
);
320 // Low Level Communication Management
324 Verify that the indexes for a ring are valid.
326 The difference between the producer and consumer cannot
327 exceed the size of the ring.
329 @param Cons The consumer index for the ring to test.
330 @param Prod The producer index for the ring to test.
332 @retval TRUE If indexes are in range.
333 @retval FALSE If the indexes are out of range.
337 XenStoreCheckIndexes (
338 XENSTORE_RING_IDX Cons
,
339 XENSTORE_RING_IDX Prod
342 return ((Prod
- Cons
) <= XENSTORE_RING_SIZE
);
346 Return a pointer to, and the length of, the contiguous
347 free region available for output in a ring buffer.
349 @param Cons The consumer index for the ring.
350 @param Prod The producer index for the ring.
351 @param Buffer The base address of the ring's storage.
352 @param LenPtr The amount of contiguous storage available.
354 @return A pointer to the start location of the free region.
358 XenStoreGetOutputChunk (
359 IN XENSTORE_RING_IDX Cons
,
360 IN XENSTORE_RING_IDX Prod
,
366 Len
= XENSTORE_RING_SIZE
- MASK_XENSTORE_IDX (Prod
);
367 if ((XENSTORE_RING_SIZE
- (Prod
- Cons
)) < Len
) {
368 Len
= XENSTORE_RING_SIZE
- (Prod
- Cons
);
371 return (Buffer
+ MASK_XENSTORE_IDX (Prod
));
375 Return a pointer to, and the length of, the contiguous
376 data available to read from a ring buffer.
378 @param Cons The consumer index for the ring.
379 @param Prod The producer index for the ring.
380 @param Buffer The base address of the ring's storage.
381 @param LenPtr The amount of contiguous data available to read.
383 @return A pointer to the start location of the available data.
387 XenStoreGetInputChunk (
388 IN XENSTORE_RING_IDX Cons
,
389 IN XENSTORE_RING_IDX Prod
,
390 IN CONST CHAR8
*Buffer
,
396 Len
= XENSTORE_RING_SIZE
- MASK_XENSTORE_IDX (Cons
);
397 if ((Prod
- Cons
) < Len
) {
401 return (Buffer
+ MASK_XENSTORE_IDX (Cons
));
405 Wait for an event or timeout.
407 @param Event Event to wait for.
408 @param Timeout A timeout value in 100ns units.
410 @retval EFI_SUCCESS Event have been triggered or the current TPL is not
412 @retval EFI_TIMEOUT Timeout have expired.
416 XenStoreWaitForEvent (
423 EFI_EVENT TimerEvent
;
424 EFI_EVENT WaitList
[2];
426 gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
427 gBS
->SetTimer (TimerEvent
, TimerRelative
, Timeout
);
429 WaitList
[0] = xs
.EventChannelEvent
;
430 WaitList
[1] = TimerEvent
;
431 Status
= gBS
->WaitForEvent (2, WaitList
, &Index
);
432 ASSERT (Status
!= EFI_INVALID_PARAMETER
);
433 gBS
->CloseEvent (TimerEvent
);
434 if (Status
== EFI_UNSUPPORTED
) {
445 Transmit data to the XenStore service.
447 The buffer pointed to by DataPtr is at least Len bytes in length.
449 @param DataPtr A pointer to the contiguous data to send.
450 @param Len The amount of data to send.
452 @return On success 0, otherwise an errno value indicating the
458 IN CONST VOID
*DataPtr
,
462 XENSTORE_RING_IDX Cons
, Prod
;
463 CONST CHAR8
*Data
= (CONST CHAR8
*)DataPtr
;
469 Cons
= xs
.XenStore
->req_cons
;
470 Prod
= xs
.XenStore
->req_prod
;
471 if ((Prod
- Cons
) == XENSTORE_RING_SIZE
) {
473 * Output ring is full. Wait for a ring event.
475 * Note that the events from both queues are combined, so being woken
476 * does not guarantee that data exist in the read ring.
480 Status
= XenStoreWaitForEvent (xs
.EventChannelEvent
,
481 EFI_TIMER_PERIOD_SECONDS (1));
482 if (Status
== EFI_TIMEOUT
) {
483 DEBUG ((EFI_D_WARN
, "XenStore Write, waiting for a ring event.\n"));
488 /* Verify queue sanity. */
489 if (!XenStoreCheckIndexes (Cons
, Prod
)) {
490 xs
.XenStore
->req_cons
= xs
.XenStore
->req_prod
= 0;
491 return XENSTORE_STATUS_EIO
;
494 Dest
= XenStoreGetOutputChunk (Cons
, Prod
, xs
.XenStore
->req
, &Available
);
495 if (Available
> Len
) {
499 CopyMem (Dest
, Data
, Available
);
504 * The store to the producer index, which indicates
505 * to the other side that new data has arrived, must
506 * be visible only after our copy of the data into the
507 * ring has completed.
510 xs
.XenStore
->req_prod
+= Available
;
513 * The other side will see the change to req_prod at the time of the
517 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
520 return XENSTORE_STATUS_SUCCESS
;
524 Receive data from the XenStore service.
526 The buffer pointed to by DataPtr is at least Len bytes in length.
528 @param DataPtr A pointer to the contiguous buffer to receive the data.
529 @param Len The amount of data to receive.
531 @return On success 0, otherwise an errno value indicating the
541 XENSTORE_RING_IDX Cons
, Prod
;
542 CHAR8
*Data
= (CHAR8
*) DataPtr
;
548 Cons
= xs
.XenStore
->rsp_cons
;
549 Prod
= xs
.XenStore
->rsp_prod
;
552 * Nothing to read. Wait for a ring event.
554 * Note that the events from both queues are combined, so being woken
555 * does not guarantee that data exist in the read ring.
559 Status
= XenStoreWaitForEvent (xs
.EventChannelEvent
,
560 EFI_TIMER_PERIOD_SECONDS (1));
561 if (Status
== EFI_TIMEOUT
) {
562 DEBUG ((EFI_D_WARN
, "XenStore Read, waiting for a ring event.\n"));
567 /* Verify queue sanity. */
568 if (!XenStoreCheckIndexes (Cons
, Prod
)) {
569 xs
.XenStore
->rsp_cons
= xs
.XenStore
->rsp_prod
= 0;
570 return XENSTORE_STATUS_EIO
;
573 Src
= XenStoreGetInputChunk (Cons
, Prod
, xs
.XenStore
->rsp
, &Available
);
574 if (Available
> Len
) {
579 * Insure the data we read is related to the indexes
584 CopyMem (Data
, Src
, Available
);
589 * Insure that the producer of this ring does not see
590 * the ring space as free until after we have copied it
594 xs
.XenStore
->rsp_cons
+= Available
;
597 * The producer will see the updated consumer index when the event is
601 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
604 return XENSTORE_STATUS_SUCCESS
;
608 // Received Message Processing
612 Block reading the next message from the XenStore service and
615 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno value
616 indicating the type of failure encountered.
620 XenStoreProcessMessage (
624 XENSTORE_MESSAGE
*Message
;
626 XENSTORE_STATUS Status
;
628 Message
= AllocateZeroPool (sizeof (XENSTORE_MESSAGE
));
629 Message
->Signature
= XENSTORE_MESSAGE_SIGNATURE
;
630 Status
= XenStoreReadStore (&Message
->Header
, sizeof (Message
->Header
));
631 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
633 DEBUG ((EFI_D_ERROR
, "XenStore: Error read store (%d)\n", Status
));
637 Body
= AllocatePool (Message
->Header
.len
+ 1);
638 Status
= XenStoreReadStore (Body
, Message
->Header
.len
);
639 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
642 DEBUG ((EFI_D_ERROR
, "XenStore: Error read store (%d)\n", Status
));
645 Body
[Message
->Header
.len
] = '\0';
647 if (Message
->Header
.type
== XS_WATCH_EVENT
) {
648 Message
->u
.Watch
.Vector
= Split(Body
, Message
->Header
.len
,
649 &Message
->u
.Watch
.VectorSize
);
651 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
652 Message
->u
.Watch
.Handle
=
653 XenStoreFindWatch (Message
->u
.Watch
.Vector
[XS_WATCH_TOKEN
]);
654 DEBUG ((EFI_D_INFO
, "XenStore: Watch event %a\n",
655 Message
->u
.Watch
.Vector
[XS_WATCH_TOKEN
]));
656 if (Message
->u
.Watch
.Handle
!= NULL
) {
657 EfiAcquireLock (&xs
.WatchEventsLock
);
658 InsertHeadList (&xs
.WatchEvents
, &Message
->Link
);
659 EfiReleaseLock (&xs
.WatchEventsLock
);
661 DEBUG ((EFI_D_WARN
, "XenStore: Watch handle %a not found\n",
662 Message
->u
.Watch
.Vector
[XS_WATCH_TOKEN
]));
663 FreePool(Message
->u
.Watch
.Vector
);
666 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
668 Message
->u
.Reply
.Body
= Body
;
669 EfiAcquireLock (&xs
.ReplyLock
);
670 InsertTailList (&xs
.ReplyList
, &Message
->Link
);
671 EfiReleaseLock (&xs
.ReplyLock
);
674 return XENSTORE_STATUS_SUCCESS
;
678 // XenStore Message Request/Reply Processing
682 Convert a XenStore error string into an errno number.
684 Unknown error strings are converted to EINVAL.
686 @param errorstring The error string to convert.
688 @return The errno best matching the input string.
692 XENSTORE_STATUS Status
;
693 CONST CHAR8
*ErrorStr
;
696 static XenStoreErrors gXenStoreErrors
[] = {
697 { XENSTORE_STATUS_EINVAL
, "EINVAL" },
698 { XENSTORE_STATUS_EACCES
, "EACCES" },
699 { XENSTORE_STATUS_EEXIST
, "EEXIST" },
700 { XENSTORE_STATUS_EISDIR
, "EISDIR" },
701 { XENSTORE_STATUS_ENOENT
, "ENOENT" },
702 { XENSTORE_STATUS_ENOMEM
, "ENOMEM" },
703 { XENSTORE_STATUS_ENOSPC
, "ENOSPC" },
704 { XENSTORE_STATUS_EIO
, "EIO" },
705 { XENSTORE_STATUS_ENOTEMPTY
, "ENOTEMPTY" },
706 { XENSTORE_STATUS_ENOSYS
, "ENOSYS" },
707 { XENSTORE_STATUS_EROFS
, "EROFS" },
708 { XENSTORE_STATUS_EBUSY
, "EBUSY" },
709 { XENSTORE_STATUS_EAGAIN
, "EAGAIN" },
710 { XENSTORE_STATUS_EISCONN
, "EISCONN" },
711 { XENSTORE_STATUS_E2BIG
, "E2BIG" }
713 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
718 CONST CHAR8
*ErrorStr
723 for (Index
= 0; Index
< ARRAY_SIZE(gXenStoreErrors
); Index
++) {
724 if (!AsciiStrCmp (ErrorStr
, gXenStoreErrors
[Index
].ErrorStr
)) {
725 return gXenStoreErrors
[Index
].Status
;
728 DEBUG ((EFI_D_WARN
, "XenStore gave unknown error %a\n", ErrorStr
));
729 return XENSTORE_STATUS_EINVAL
;
733 Block waiting for a reply to a message request.
735 @param TypePtr The returned type of the reply.
736 @param LenPtr The returned body length of the reply.
737 @param Result The returned body of the reply.
742 OUT
enum xsd_sockmsg_type
*TypePtr
,
743 OUT UINT32
*LenPtr OPTIONAL
,
747 XENSTORE_MESSAGE
*Message
;
751 while (IsListEmpty (&xs
.ReplyList
)) {
752 XENSTORE_STATUS Status
;
753 Status
= XenStoreProcessMessage ();
754 if (Status
!= XENSTORE_STATUS_SUCCESS
&& Status
!= XENSTORE_STATUS_EAGAIN
) {
755 DEBUG ((EFI_D_ERROR
, "XenStore, error while reading the ring (%d).",
760 EfiAcquireLock (&xs
.ReplyLock
);
761 Entry
= GetFirstNode (&xs
.ReplyList
);
762 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
763 RemoveEntryList (Entry
);
764 EfiReleaseLock (&xs
.ReplyLock
);
766 *TypePtr
= Message
->Header
.type
;
767 if (LenPtr
!= NULL
) {
768 *LenPtr
= Message
->Header
.len
;
770 Body
= Message
->u
.Reply
.Body
;
774 return XENSTORE_STATUS_SUCCESS
;
778 Send a message with an optionally muti-part body to the XenStore service.
780 @param Transaction The transaction to use for this request.
781 @param RequestType The type of message to send.
782 @param WriteRequest Pointers to the body sections of the request.
783 @param NumRequests The number of body sections in the request.
784 @param LenPtr The returned length of the reply.
785 @param ResultPtr The returned body of the reply.
787 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
788 the cause of failure.
793 IN CONST XENSTORE_TRANSACTION
*Transaction
,
794 IN
enum xsd_sockmsg_type RequestType
,
795 IN CONST WRITE_REQUEST
*WriteRequest
,
796 IN UINT32 NumRequests
,
797 OUT UINT32
*LenPtr OPTIONAL
,
798 OUT VOID
**ResultPtr OPTIONAL
801 struct xsd_sockmsg Message
;
804 XENSTORE_STATUS Status
;
806 if (Transaction
== XST_NIL
) {
809 Message
.tx_id
= Transaction
->Id
;
812 Message
.type
= RequestType
;
814 for (Index
= 0; Index
< NumRequests
; Index
++) {
815 Message
.len
+= WriteRequest
[Index
].Len
;
818 Status
= XenStoreWriteStore (&Message
, sizeof (Message
));
819 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
820 DEBUG ((EFI_D_ERROR
, "XenStoreTalkv failed %d\n", Status
));
824 for (Index
= 0; Index
< NumRequests
; Index
++) {
825 Status
= XenStoreWriteStore (WriteRequest
[Index
].Data
, WriteRequest
[Index
].Len
);
826 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
827 DEBUG ((EFI_D_ERROR
, "XenStoreTalkv failed %d\n", Status
));
832 Status
= XenStoreReadReply (&Message
.type
, LenPtr
, &Return
);
835 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
839 if (Message
.type
== XS_ERROR
) {
840 Status
= XenStoreGetError (Return
);
845 /* Reply is either error or an echo of our request message type. */
846 ASSERT (Message
.type
== RequestType
);
854 return XENSTORE_STATUS_SUCCESS
;
858 Wrapper for XenStoreTalkv allowing easy transmission of a message with
859 a single, contiguous, message body.
861 The returned result is provided in malloced storage and thus must be free'd
864 @param Transaction The transaction to use for this request.
865 @param RequestType The type of message to send.
866 @param Body The body of the request.
867 @param LenPtr The returned length of the reply.
868 @param Result The returned body of the reply.
870 @return 0 on success. Otherwise an errno indicating
871 the cause of failure.
876 IN CONST XENSTORE_TRANSACTION
*Transaction
,
877 IN
enum xsd_sockmsg_type RequestType
,
878 IN CONST CHAR8
*Body
,
879 OUT UINT32
*LenPtr OPTIONAL
,
880 OUT VOID
**Result OPTIONAL
883 WRITE_REQUEST WriteRequest
;
885 WriteRequest
.Data
= (VOID
*) Body
;
886 WriteRequest
.Len
= AsciiStrSize (Body
);
888 return XenStoreTalkv (Transaction
, RequestType
, &WriteRequest
, 1,
893 // XenStore Watch Support
897 Transmit a watch request to the XenStore service.
899 @param Path The path in the XenStore to watch.
900 @param Tocken A unique identifier for this watch.
902 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating the
912 WRITE_REQUEST WriteRequest
[2];
914 WriteRequest
[0].Data
= (VOID
*) Path
;
915 WriteRequest
[0].Len
= AsciiStrSize (Path
);
916 WriteRequest
[1].Data
= (VOID
*) Token
;
917 WriteRequest
[1].Len
= AsciiStrSize (Token
);
919 return XenStoreTalkv (XST_NIL
, XS_WATCH
, WriteRequest
, 2, NULL
, NULL
);
923 Transmit an uwatch request to the XenStore service.
925 @param Path The path in the XenStore to watch.
926 @param Tocken A unique identifier for this watch.
928 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
929 the cause of failure.
938 WRITE_REQUEST WriteRequest
[2];
940 WriteRequest
[0].Data
= (VOID
*) Path
;
941 WriteRequest
[0].Len
= AsciiStrSize (Path
);
942 WriteRequest
[1].Data
= (VOID
*) Token
;
943 WriteRequest
[1].Len
= AsciiStrSize (Token
);
945 return XenStoreTalkv (XST_NIL
, XS_UNWATCH
, WriteRequest
, 2, NULL
, NULL
);
954 XENSTORE_MESSAGE
*Message
;
955 LIST_ENTRY
*Entry
= NULL
;
956 LIST_ENTRY
*Last
= NULL
;
957 XENSTORE_STATUS Status
;
960 EfiAcquireLock (&xs
.WatchEventsLock
);
961 if (IsListEmpty (&xs
.WatchEvents
) ||
962 Last
== GetFirstNode (&xs
.WatchEvents
)) {
963 EfiReleaseLock (&xs
.WatchEventsLock
);
964 Status
= XenStoreProcessMessage ();
965 if (Status
!= XENSTORE_STATUS_SUCCESS
&& Status
!= XENSTORE_STATUS_EAGAIN
) {
971 for (Entry
= GetFirstNode (&xs
.WatchEvents
);
972 Entry
!= Last
&& !IsNull (&xs
.WatchEvents
, Entry
);
973 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
)) {
974 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
975 if (Message
->u
.Watch
.Handle
== Token
) {
976 RemoveEntryList (Entry
);
977 EfiReleaseLock (&xs
.WatchEventsLock
);
978 FreePool(Message
->u
.Watch
.Vector
);
980 return XENSTORE_STATUS_SUCCESS
;
983 Last
= GetFirstNode (&xs
.WatchEvents
);
984 EfiReleaseLock (&xs
.WatchEventsLock
);
990 NotifyEventChannelCheckForEvent (
995 XENSTORE_PRIVATE
*xs
;
996 xs
= (XENSTORE_PRIVATE
*)Context
;
997 if (TestAndClearBit (xs
->EventChannel
, xs
->Dev
->SharedInfo
->evtchn_pending
)) {
998 gBS
->SignalEvent (Event
);
1003 Setup communication channels with the XenStore service.
1005 @retval EFI_SUCCESS if everything went well.
1010 XENSTORE_PRIVATE
*xs
1014 EFI_EVENT TimerEvent
;
1015 struct xenstore_domain_interface
*XenStore
= xs
->XenStore
;
1017 Status
= gBS
->CreateEvent (EVT_TIMER
, 0, NULL
, NULL
, &TimerEvent
);
1018 Status
= gBS
->SetTimer (TimerEvent
, TimerRelative
,
1019 EFI_TIMER_PERIOD_SECONDS (5));
1020 while (XenStore
->rsp_prod
!= XenStore
->rsp_cons
) {
1021 Status
= gBS
->CheckEvent (TimerEvent
);
1022 if (!EFI_ERROR (Status
)) {
1023 DEBUG ((EFI_D_WARN
, "XENSTORE response ring is not quiescent "
1024 "(%08x:%08x): fixing up\n",
1025 XenStore
->rsp_cons
, XenStore
->rsp_prod
));
1026 XenStore
->rsp_cons
= XenStore
->rsp_prod
;
1029 gBS
->CloseEvent (TimerEvent
);
1031 Status
= gBS
->CreateEvent (EVT_NOTIFY_WAIT
, TPL_NOTIFY
,
1032 NotifyEventChannelCheckForEvent
, xs
,
1033 &xs
->EventChannelEvent
);
1034 ASSERT_EFI_ERROR (Status
);
1040 Initialize XenStore.
1042 @param Dev A XENBUS_DEVICE instance.
1044 @retval EFI_SUCCESS if everything went well.
1053 * The HVM guest pseudo-physical frame number. This is Xen's mapping
1054 * of the true machine frame number into our "physical address space".
1060 xs
.EventChannel
= XenHypercallHvmGetParam (Dev
, HVM_PARAM_STORE_EVTCHN
);
1061 XenStoreGpfn
= XenHypercallHvmGetParam (Dev
, HVM_PARAM_STORE_PFN
);
1062 xs
.XenStore
= (VOID
*) (XenStoreGpfn
<< EFI_PAGE_SHIFT
);
1063 DEBUG ((EFI_D_INFO
, "XenBusInit: XenBus rings @%p, event channel %x\n",
1064 xs
.XenStore
, xs
.EventChannel
));
1066 InitializeListHead (&xs
.ReplyList
);
1067 InitializeListHead (&xs
.WatchEvents
);
1068 InitializeListHead (&xs
.RegisteredWatches
);
1070 EfiInitializeLock (&xs
.ReplyLock
, TPL_NOTIFY
);
1071 EfiInitializeLock (&xs
.RegisteredWatchesLock
, TPL_NOTIFY
);
1072 EfiInitializeLock (&xs
.WatchEventsLock
, TPL_NOTIFY
);
1074 /* Initialize the shared memory rings to talk to xenstored */
1075 Status
= XenStoreInitComms (&xs
);
1076 if (EFI_ERROR (Status
)) {
1085 IN XENBUS_DEVICE
*Dev
1089 // Emptying the list RegisteredWatches, but this list should already be
1090 // empty. Every driver that is using Watches should unregister them when
1093 if (!IsListEmpty (&xs
.RegisteredWatches
)) {
1094 XENSTORE_WATCH
*Watch
;
1096 DEBUG ((EFI_D_WARN
, "XenStore: RegisteredWatches is not empty, cleaning up..."));
1097 Entry
= GetFirstNode (&xs
.RegisteredWatches
);
1098 while (!IsNull (&xs
.RegisteredWatches
, Entry
)) {
1099 Watch
= XENSTORE_WATCH_FROM_LINK (Entry
);
1100 Entry
= GetNextNode (&xs
.RegisteredWatches
, Entry
);
1102 XenStoreUnregisterWatch (Watch
);
1107 // Emptying the list WatchEvents, but this list should already be empty after
1108 // having cleanup the list RegisteredWatches.
1110 if (!IsListEmpty (&xs
.WatchEvents
)) {
1112 DEBUG ((EFI_D_WARN
, "XenStore: WatchEvents is not empty, cleaning up..."));
1113 Entry
= GetFirstNode (&xs
.WatchEvents
);
1114 while (!IsNull (&xs
.WatchEvents
, Entry
)) {
1115 XENSTORE_MESSAGE
*Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1116 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
);
1117 RemoveEntryList (&Message
->Link
);
1118 FreePool (Message
->u
.Watch
.Vector
);
1123 if (!IsListEmpty (&xs
.ReplyList
)) {
1124 XENSTORE_MESSAGE
*Message
;
1126 Entry
= GetFirstNode (&xs
.ReplyList
);
1127 while (!IsNull (&xs
.ReplyList
, Entry
)) {
1128 Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1129 Entry
= GetNextNode (&xs
.ReplyList
, Entry
);
1130 RemoveEntryList (&Message
->Link
);
1131 FreePool (Message
->u
.Reply
.Body
);
1136 gBS
->CloseEvent (xs
.EventChannelEvent
);
1138 if (xs
.XenStore
->server_features
& XENSTORE_SERVER_FEATURE_RECONNECTION
) {
1139 xs
.XenStore
->connection
= XENSTORE_RECONNECT
;
1140 XenEventChannelNotify (xs
.Dev
, xs
.EventChannel
);
1141 while (*(volatile UINT32
*)&xs
.XenStore
->connection
== XENSTORE_RECONNECT
) {
1142 XenStoreWaitForEvent (xs
.EventChannelEvent
, EFI_TIMER_PERIOD_MILLISECONDS (100));
1145 /* If the backend reads the state while we're erasing it then the
1146 * ring state will become corrupted, preventing guest frontends from
1147 * connecting. This is rare. To help diagnose the failure, we fill
1148 * the ring with XS_INVALID packets. */
1149 SetMem (xs
.XenStore
->req
, XENSTORE_RING_SIZE
, 0xff);
1150 SetMem (xs
.XenStore
->rsp
, XENSTORE_RING_SIZE
, 0xff);
1151 xs
.XenStore
->req_cons
= xs
.XenStore
->req_prod
= 0;
1152 xs
.XenStore
->rsp_cons
= xs
.XenStore
->rsp_prod
= 0;
1159 // API comments for these methods can be found in XenStore.h
1163 XenStoreListDirectory (
1164 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1165 IN CONST CHAR8
*DirectoryPath
,
1166 IN CONST CHAR8
*Node
,
1167 OUT UINT32
*DirectoryCountPtr
,
1168 OUT CONST CHAR8
***DirectoryListPtr
1174 XENSTORE_STATUS Status
;
1176 Path
= XenStoreJoin (DirectoryPath
, Node
);
1177 Status
= XenStoreSingle (Transaction
, XS_DIRECTORY
, Path
, &Len
,
1178 (VOID
**) &TempStr
);
1180 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1184 *DirectoryListPtr
= Split (TempStr
, Len
, DirectoryCountPtr
);
1186 return XENSTORE_STATUS_SUCCESS
;
1190 XenStorePathExists (
1191 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1192 IN CONST CHAR8
*Directory
,
1193 IN CONST CHAR8
*Node
1196 CONST CHAR8
**TempStr
;
1197 XENSTORE_STATUS Status
;
1200 Status
= XenStoreListDirectory (Transaction
, Directory
, Node
,
1201 &TempNum
, &TempStr
);
1202 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1211 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1212 IN CONST CHAR8
*DirectoryPath
,
1213 IN CONST CHAR8
*Node
,
1214 OUT UINT32
*LenPtr OPTIONAL
,
1220 XENSTORE_STATUS Status
;
1222 Path
= XenStoreJoin (DirectoryPath
, Node
);
1223 Status
= XenStoreSingle (Transaction
, XS_READ
, Path
, LenPtr
, &Value
);
1225 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
1230 return XENSTORE_STATUS_SUCCESS
;
1235 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1236 IN CONST CHAR8
*DirectoryPath
,
1237 IN CONST CHAR8
*Node
,
1242 WRITE_REQUEST WriteRequest
[2];
1243 XENSTORE_STATUS Status
;
1245 Path
= XenStoreJoin (DirectoryPath
, Node
);
1247 WriteRequest
[0].Data
= (VOID
*) Path
;
1248 WriteRequest
[0].Len
= AsciiStrSize (Path
);
1249 WriteRequest
[1].Data
= (VOID
*) Str
;
1250 WriteRequest
[1].Len
= AsciiStrLen (Str
);
1252 Status
= XenStoreTalkv (Transaction
, XS_WRITE
, WriteRequest
, 2, NULL
, NULL
);
1260 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1261 IN CONST CHAR8
*DirectoryPath
,
1262 IN CONST CHAR8
*Node
1266 XENSTORE_STATUS Status
;
1268 Path
= XenStoreJoin (DirectoryPath
, Node
);
1269 Status
= XenStoreSingle (Transaction
, XS_RM
, Path
, NULL
, NULL
);
1276 XenStoreTransactionStart (
1277 OUT XENSTORE_TRANSACTION
*Transaction
1281 XENSTORE_STATUS Status
;
1283 Status
= XenStoreSingle (XST_NIL
, XS_TRANSACTION_START
, "", NULL
,
1285 if (Status
== XENSTORE_STATUS_SUCCESS
) {
1286 Transaction
->Id
= AsciiStrDecimalToUintn (IdStr
);
1294 XenStoreTransactionEnd (
1295 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1302 AsciiStrCpy (AbortStr
, "F");
1304 AsciiStrCpy (AbortStr
, "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
;
1323 BufSize
= SPrintLengthAsciiFormat (FormatString
, Marker
) + 1;
1324 Buf
= AllocateZeroPool (BufSize
);
1325 AsciiVSPrint (Buf
, BufSize
, FormatString
, Marker
);
1326 Status
= XenStoreWrite (Transaction
, DirectoryPath
, Node
, Buf
);
1335 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1336 IN CONST CHAR8
*DirectoryPath
,
1337 IN CONST CHAR8
*Node
,
1338 IN CONST CHAR8
*FormatString
,
1343 XENSTORE_STATUS Status
;
1345 VA_START (Marker
, FormatString
);
1346 Status
= XenStoreVSPrint (Transaction
, DirectoryPath
, Node
, FormatString
, Marker
);
1353 XenStoreRegisterWatch (
1354 IN CONST CHAR8
*DirectoryPath
,
1355 IN CONST CHAR8
*Node
,
1356 OUT XENSTORE_WATCH
**WatchPtr
1359 /* Pointer in ascii is the token. */
1360 CHAR8 Token
[sizeof (XENSTORE_WATCH
) * 2 + 1];
1361 XENSTORE_STATUS Status
;
1362 XENSTORE_WATCH
*Watch
;
1364 Watch
= AllocateZeroPool (sizeof (XENSTORE_WATCH
));
1365 Watch
->Signature
= XENSTORE_WATCH_SIGNATURE
;
1366 Watch
->Node
= XenStoreJoin (DirectoryPath
, Node
);
1368 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1369 InsertTailList (&xs
.RegisteredWatches
, &Watch
->Link
);
1370 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1372 AsciiSPrint (Token
, sizeof (Token
), "%p", (VOID
*) Watch
);
1373 Status
= XenStoreWatch (Watch
->Node
, Token
);
1375 /* Ignore errors due to multiple registration. */
1376 if (Status
== XENSTORE_STATUS_EEXIST
) {
1377 Status
= XENSTORE_STATUS_SUCCESS
;
1380 if (Status
== XENSTORE_STATUS_SUCCESS
) {
1383 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1384 RemoveEntryList (&Watch
->Link
);
1385 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1386 FreePool (Watch
->Node
);
1394 XenStoreUnregisterWatch (
1395 IN XENSTORE_WATCH
*Watch
1398 CHAR8 Token
[sizeof (Watch
) * 2 + 1];
1401 ASSERT (Watch
->Signature
== XENSTORE_WATCH_SIGNATURE
);
1403 AsciiSPrint (Token
, sizeof (Token
), "%p", (VOID
*) Watch
);
1404 if (XenStoreFindWatch (Token
) == NULL
) {
1408 EfiAcquireLock (&xs
.RegisteredWatchesLock
);
1409 RemoveEntryList (&Watch
->Link
);
1410 EfiReleaseLock (&xs
.RegisteredWatchesLock
);
1412 XenStoreUnwatch (Watch
->Node
, Token
);
1414 /* Cancel pending watch events. */
1415 EfiAcquireLock (&xs
.WatchEventsLock
);
1416 Entry
= GetFirstNode (&xs
.WatchEvents
);
1417 while (!IsNull (&xs
.WatchEvents
, Entry
)) {
1418 XENSTORE_MESSAGE
*Message
= XENSTORE_MESSAGE_FROM_LINK (Entry
);
1419 Entry
= GetNextNode (&xs
.WatchEvents
, Entry
);
1420 if (Message
->u
.Watch
.Handle
== Watch
) {
1421 RemoveEntryList (&Message
->Link
);
1422 FreePool (Message
->u
.Watch
.Vector
);
1426 EfiReleaseLock (&xs
.WatchEventsLock
);
1428 FreePool (Watch
->Node
);
1439 XenBusWaitForWatch (
1440 IN XENBUS_PROTOCOL
*This
,
1444 return XenStoreWaitWatch (Token
);
1449 XenBusXenStoreRead (
1450 IN XENBUS_PROTOCOL
*This
,
1451 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1452 IN CONST CHAR8
*Node
,
1456 return XenStoreRead (Transaction
, This
->Node
, Node
, NULL
, Value
);
1461 XenBusXenStoreBackendRead (
1462 IN XENBUS_PROTOCOL
*This
,
1463 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1464 IN CONST CHAR8
*Node
,
1468 return XenStoreRead (Transaction
, This
->Backend
, Node
, NULL
, Value
);
1473 XenBusXenStoreRemove (
1474 IN XENBUS_PROTOCOL
*This
,
1475 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1479 return XenStoreRemove (Transaction
, This
->Node
, Node
);
1484 XenBusXenStoreTransactionStart (
1485 IN XENBUS_PROTOCOL
*This
,
1486 OUT XENSTORE_TRANSACTION
*Transaction
1489 return XenStoreTransactionStart (Transaction
);
1494 XenBusXenStoreTransactionEnd (
1495 IN XENBUS_PROTOCOL
*This
,
1496 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1500 return XenStoreTransactionEnd (Transaction
, Abort
);
1505 XenBusXenStoreSPrint (
1506 IN XENBUS_PROTOCOL
*This
,
1507 IN CONST XENSTORE_TRANSACTION
*Transaction
,
1508 IN CONST CHAR8
*DirectoryPath
,
1509 IN CONST CHAR8
*Node
,
1510 IN CONST CHAR8
*FormatString
,
1515 XENSTORE_STATUS Status
;
1517 VA_START (Marker
, FormatString
);
1518 Status
= XenStoreVSPrint (Transaction
, DirectoryPath
, Node
, FormatString
, Marker
);
1526 XenBusRegisterWatch (
1527 IN XENBUS_PROTOCOL
*This
,
1528 IN CONST CHAR8
*Node
,
1532 return XenStoreRegisterWatch (This
->Node
, Node
, (XENSTORE_WATCH
**) Token
);
1537 XenBusRegisterWatchBackend (
1538 IN XENBUS_PROTOCOL
*This
,
1539 IN CONST CHAR8
*Node
,
1543 return XenStoreRegisterWatch (This
->Backend
, Node
, (XENSTORE_WATCH
**) Token
);
1548 XenBusUnregisterWatch (
1549 IN XENBUS_PROTOCOL
*This
,
1553 XenStoreUnregisterWatch ((XENSTORE_WATCH
*) Token
);