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