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