]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/XenBusDxe/XenStore.c
4b99c9ca1fd8b772a2aa6d5b2303e1b902d64b84
[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 hierachy
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 "XenHypercall.h"
64 #include "EventChannel.h"
65
66 //
67 // Private Data Structures
68 //
69
70 typedef struct {
71 CONST VOID *Data;
72 UINTN 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 (&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
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);
314 }
315
316 return Buf;
317 }
318
319 //
320 // Low Level Communication Management
321 //
322
323 /**
324 Verify that the indexes for a ring are valid.
325
326 The difference between the producer and consumer cannot
327 exceed the size of the ring.
328
329 @param Cons The consumer index for the ring to test.
330 @param Prod The producer index for the ring to test.
331
332 @retval TRUE If indexes are in range.
333 @retval FALSE If the indexes are out of range.
334 **/
335 STATIC
336 BOOLEAN
337 XenStoreCheckIndexes (
338 XENSTORE_RING_IDX Cons,
339 XENSTORE_RING_IDX Prod
340 )
341 {
342 return ((Prod - Cons) <= XENSTORE_RING_SIZE);
343 }
344
345 /**
346 Return a pointer to, and the length of, the contiguous
347 free region available for output in a ring buffer.
348
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.
353
354 @return A pointer to the start location of the free region.
355 **/
356 STATIC
357 VOID *
358 XenStoreGetOutputChunk (
359 IN XENSTORE_RING_IDX Cons,
360 IN XENSTORE_RING_IDX Prod,
361 IN CHAR8 *Buffer,
362 OUT UINT32 *LenPtr
363 )
364 {
365 UINT32 Len;
366 Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Prod);
367 if ((XENSTORE_RING_SIZE - (Prod - Cons)) < Len) {
368 Len = XENSTORE_RING_SIZE - (Prod - Cons);
369 }
370 *LenPtr = Len;
371 return (Buffer + MASK_XENSTORE_IDX (Prod));
372 }
373
374 /**
375 Return a pointer to, and the length of, the contiguous
376 data available to read from a ring buffer.
377
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.
382
383 @return A pointer to the start location of the available data.
384 **/
385 STATIC
386 CONST VOID *
387 XenStoreGetInputChunk (
388 IN XENSTORE_RING_IDX Cons,
389 IN XENSTORE_RING_IDX Prod,
390 IN CONST CHAR8 *Buffer,
391 OUT UINT32 *LenPtr
392 )
393 {
394 UINT32 Len;
395
396 Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Cons);
397 if ((Prod - Cons) < Len) {
398 Len = Prod - Cons;
399 }
400 *LenPtr = Len;
401 return (Buffer + MASK_XENSTORE_IDX (Cons));
402 }
403
404 /**
405 Wait for an event or timeout.
406
407 @param Event Event to wait for.
408 @param Timeout A timeout value in 100ns units.
409
410 @retval EFI_SUCCESS Event have been triggered or the current TPL is not
411 TPL_APPLICATION.
412 @retval EFI_TIMEOUT Timeout have expired.
413 **/
414 STATIC
415 EFI_STATUS
416 XenStoreWaitForEvent (
417 IN EFI_EVENT Event,
418 IN UINT64 Timeout
419 )
420 {
421 UINTN Index;
422 EFI_STATUS Status;
423 EFI_EVENT TimerEvent;
424 EFI_EVENT WaitList[2];
425
426 gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
427 gBS->SetTimer (TimerEvent, TimerRelative, Timeout);
428
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) {
435 return EFI_SUCCESS;
436 }
437 if (Index == 1) {
438 return EFI_TIMEOUT;
439 } else {
440 return EFI_SUCCESS;
441 }
442 }
443
444 /**
445 Transmit data to the XenStore service.
446
447 The buffer pointed to by DataPtr is at least Len bytes in length.
448
449 @param DataPtr A pointer to the contiguous data to send.
450 @param Len The amount of data to send.
451
452 @return On success 0, otherwise an errno value indicating the
453 cause of failure.
454 **/
455 STATIC
456 XENSTORE_STATUS
457 XenStoreWriteStore (
458 IN CONST VOID *DataPtr,
459 IN UINTN Len
460 )
461 {
462 XENSTORE_RING_IDX Cons, Prod;
463 CONST CHAR8 *Data = (CONST CHAR8 *)DataPtr;
464
465 while (Len != 0) {
466 void *Dest;
467 UINT32 Available;
468
469 Cons = xs.XenStore->req_cons;
470 Prod = xs.XenStore->req_prod;
471 if ((Prod - Cons) == XENSTORE_RING_SIZE) {
472 /*
473 * Output ring is full. Wait for a ring event.
474 *
475 * Note that the events from both queues are combined, so being woken
476 * does not guarantee that data exist in the read ring.
477 */
478 EFI_STATUS Status;
479
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"));
484 }
485 continue;
486 }
487
488 /* Verify queue sanity. */
489 if (!XenStoreCheckIndexes (Cons, Prod)) {
490 xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
491 return XENSTORE_STATUS_EIO;
492 }
493
494 Dest = XenStoreGetOutputChunk (Cons, Prod, xs.XenStore->req, &Available);
495 if (Available > Len) {
496 Available = Len;
497 }
498
499 CopyMem (Dest, Data, Available);
500 Data += Available;
501 Len -= Available;
502
503 /*
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.
508 */
509 MemoryFence ();
510 xs.XenStore->req_prod += Available;
511
512 /*
513 * The other side will see the change to req_prod at the time of the
514 * interrupt.
515 */
516 MemoryFence ();
517 XenEventChannelNotify (xs.Dev, xs.EventChannel);
518 }
519
520 return XENSTORE_STATUS_SUCCESS;
521 }
522
523 /**
524 Receive data from the XenStore service.
525
526 The buffer pointed to by DataPtr is at least Len bytes in length.
527
528 @param DataPtr A pointer to the contiguous buffer to receive the data.
529 @param Len The amount of data to receive.
530
531 @return On success 0, otherwise an errno value indicating the
532 cause of failure.
533 **/
534 STATIC
535 XENSTORE_STATUS
536 XenStoreReadStore (
537 OUT VOID *DataPtr,
538 IN UINTN Len
539 )
540 {
541 XENSTORE_RING_IDX Cons, Prod;
542 CHAR8 *Data = (CHAR8 *) DataPtr;
543
544 while (Len != 0) {
545 UINT32 Available;
546 CONST CHAR8 *Src;
547
548 Cons = xs.XenStore->rsp_cons;
549 Prod = xs.XenStore->rsp_prod;
550 if (Cons == Prod) {
551 /*
552 * Nothing to read. Wait for a ring event.
553 *
554 * Note that the events from both queues are combined, so being woken
555 * does not guarantee that data exist in the read ring.
556 */
557 EFI_STATUS Status;
558
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"));
563 }
564 continue;
565 }
566
567 /* Verify queue sanity. */
568 if (!XenStoreCheckIndexes (Cons, Prod)) {
569 xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
570 return XENSTORE_STATUS_EIO;
571 }
572
573 Src = XenStoreGetInputChunk (Cons, Prod, xs.XenStore->rsp, &Available);
574 if (Available > Len) {
575 Available = Len;
576 }
577
578 /*
579 * Insure the data we read is related to the indexes
580 * we read above.
581 */
582 MemoryFence ();
583
584 CopyMem (Data, Src, Available);
585 Data += Available;
586 Len -= Available;
587
588 /*
589 * Insure that the producer of this ring does not see
590 * the ring space as free until after we have copied it
591 * out.
592 */
593 MemoryFence ();
594 xs.XenStore->rsp_cons += Available;
595
596 /*
597 * The producer will see the updated consumer index when the event is
598 * delivered.
599 */
600 MemoryFence ();
601 XenEventChannelNotify (xs.Dev, xs.EventChannel);
602 }
603
604 return XENSTORE_STATUS_SUCCESS;
605 }
606
607 //
608 // Received Message Processing
609 //
610
611 /**
612 Block reading the next message from the XenStore service and
613 process the result.
614
615 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno value
616 indicating the type of failure encountered.
617 **/
618 STATIC
619 XENSTORE_STATUS
620 XenStoreProcessMessage (
621 VOID
622 )
623 {
624 XENSTORE_MESSAGE *Message;
625 CHAR8 *Body;
626 XENSTORE_STATUS Status;
627
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) {
632 FreePool (Message);
633 DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
634 return Status;
635 }
636
637 Body = AllocatePool (Message->Header.len + 1);
638 Status = XenStoreReadStore (Body, Message->Header.len);
639 if (Status != XENSTORE_STATUS_SUCCESS) {
640 FreePool (Body);
641 FreePool (Message);
642 DEBUG ((EFI_D_ERROR, "XenStore: Error read store (%d)\n", Status));
643 return Status;
644 }
645 Body[Message->Header.len] = '\0';
646
647 if (Message->Header.type == XS_WATCH_EVENT) {
648 Message->u.Watch.Vector = Split(Body, Message->Header.len,
649 &Message->u.Watch.VectorSize);
650
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);
660 } else {
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);
664 FreePool(Message);
665 }
666 EfiReleaseLock (&xs.RegisteredWatchesLock);
667 } else {
668 Message->u.Reply.Body = Body;
669 EfiAcquireLock (&xs.ReplyLock);
670 InsertTailList (&xs.ReplyList, &Message->Link);
671 EfiReleaseLock (&xs.ReplyLock);
672 }
673
674 return XENSTORE_STATUS_SUCCESS;
675 }
676
677 //
678 // XenStore Message Request/Reply Processing
679 //
680
681 /**
682 Convert a XenStore error string into an errno number.
683
684 Unknown error strings are converted to EINVAL.
685
686 @param errorstring The error string to convert.
687
688 @return The errno best matching the input string.
689
690 **/
691 typedef struct {
692 XENSTORE_STATUS Status;
693 CONST CHAR8 *ErrorStr;
694 } XenStoreErrors;
695
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" }
712 };
713 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
714
715 STATIC
716 XENSTORE_STATUS
717 XenStoreGetError (
718 CONST CHAR8 *ErrorStr
719 )
720 {
721 UINT32 Index;
722
723 for (Index = 0; Index < ARRAY_SIZE(gXenStoreErrors); Index++) {
724 if (!AsciiStrCmp (ErrorStr, gXenStoreErrors[Index].ErrorStr)) {
725 return gXenStoreErrors[Index].Status;
726 }
727 }
728 DEBUG ((EFI_D_WARN, "XenStore gave unknown error %a\n", ErrorStr));
729 return XENSTORE_STATUS_EINVAL;
730 }
731
732 /**
733 Block waiting for a reply to a message request.
734
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.
738 **/
739 STATIC
740 XENSTORE_STATUS
741 XenStoreReadReply (
742 OUT enum xsd_sockmsg_type *TypePtr,
743 OUT UINT32 *LenPtr OPTIONAL,
744 OUT VOID **Result
745 )
746 {
747 XENSTORE_MESSAGE *Message;
748 LIST_ENTRY *Entry;
749 CHAR8 *Body;
750
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).",
756 Status));
757 return Status;
758 }
759 }
760 EfiAcquireLock (&xs.ReplyLock);
761 Entry = GetFirstNode (&xs.ReplyList);
762 Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
763 RemoveEntryList (Entry);
764 EfiReleaseLock (&xs.ReplyLock);
765
766 *TypePtr = Message->Header.type;
767 if (LenPtr != NULL) {
768 *LenPtr = Message->Header.len;
769 }
770 Body = Message->u.Reply.Body;
771
772 FreePool (Message);
773 *Result = Body;
774 return XENSTORE_STATUS_SUCCESS;
775 }
776
777 /**
778 Send a message with an optionally muti-part body to the XenStore service.
779
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.
786
787 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
788 the cause of failure.
789 **/
790 STATIC
791 XENSTORE_STATUS
792 XenStoreTalkv (
793 IN 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
799 )
800 {
801 struct xsd_sockmsg Message;
802 void *Return = NULL;
803 UINT32 Index;
804 XENSTORE_STATUS Status;
805
806 Message.tx_id = Transaction.Id;
807 Message.req_id = 0;
808 Message.type = RequestType;
809 Message.len = 0;
810 for (Index = 0; Index < NumRequests; Index++) {
811 Message.len += WriteRequest[Index].Len;
812 }
813
814 Status = XenStoreWriteStore (&Message, sizeof (Message));
815 if (Status != XENSTORE_STATUS_SUCCESS) {
816 DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
817 goto Error;
818 }
819
820 for (Index = 0; Index < NumRequests; Index++) {
821 Status = XenStoreWriteStore (WriteRequest[Index].Data, WriteRequest[Index].Len);
822 if (Status != XENSTORE_STATUS_SUCCESS) {
823 DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status));
824 goto Error;
825 }
826 }
827
828 Status = XenStoreReadReply (&Message.type, LenPtr, &Return);
829
830 Error:
831 if (Status != XENSTORE_STATUS_SUCCESS) {
832 return Status;
833 }
834
835 if (Message.type == XS_ERROR) {
836 Status = XenStoreGetError (Return);
837 FreePool (Return);
838 return Status;
839 }
840
841 /* Reply is either error or an echo of our request message type. */
842 ASSERT (Message.type == RequestType);
843
844 if (ResultPtr) {
845 *ResultPtr = Return;
846 } else {
847 FreePool (Return);
848 }
849
850 return XENSTORE_STATUS_SUCCESS;
851 }
852
853 /**
854 Wrapper for XenStoreTalkv allowing easy transmission of a message with
855 a single, contiguous, message body.
856
857 The returned result is provided in malloced storage and thus must be free'd
858 by the caller.
859
860 @param Transaction The transaction to use for this request.
861 @param RequestType The type of message to send.
862 @param Body The body of the request.
863 @param LenPtr The returned length of the reply.
864 @param Result The returned body of the reply.
865
866 @return 0 on success. Otherwise an errno indicating
867 the cause of failure.
868 **/
869 STATIC
870 XENSTORE_STATUS
871 XenStoreSingle (
872 IN XENSTORE_TRANSACTION Transaction,
873 IN enum xsd_sockmsg_type RequestType,
874 IN CONST CHAR8 *Body,
875 OUT UINT32 *LenPtr OPTIONAL,
876 OUT VOID **Result OPTIONAL
877 )
878 {
879 WRITE_REQUEST WriteRequest;
880
881 WriteRequest.Data = (VOID *) Body;
882 WriteRequest.Len = AsciiStrSize (Body);
883
884 return XenStoreTalkv (Transaction, RequestType, &WriteRequest, 1,
885 LenPtr, Result);
886 }
887
888 //
889 // XenStore Watch Support
890 //
891
892 /**
893 Transmit a watch request to the XenStore service.
894
895 @param Path The path in the XenStore to watch.
896 @param Tocken A unique identifier for this watch.
897
898 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating the
899 cause of failure.
900 **/
901 STATIC
902 XENSTORE_STATUS
903 XenStoreWatch (
904 CONST CHAR8 *Path,
905 CONST CHAR8 *Token
906 )
907 {
908 WRITE_REQUEST WriteRequest[2];
909
910 WriteRequest[0].Data = (VOID *) Path;
911 WriteRequest[0].Len = AsciiStrSize (Path);
912 WriteRequest[1].Data = (VOID *) Token;
913 WriteRequest[1].Len = AsciiStrSize (Token);
914
915 return XenStoreTalkv (XST_NIL, XS_WATCH, WriteRequest, 2, NULL, NULL);
916 }
917
918 /**
919 Transmit an uwatch request to the XenStore service.
920
921 @param Path The path in the XenStore to watch.
922 @param Tocken A unique identifier for this watch.
923
924 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
925 the cause of failure.
926 **/
927 STATIC
928 XENSTORE_STATUS
929 XenStoreUnwatch (
930 CONST CHAR8 *Path,
931 CONST CHAR8 *Token
932 )
933 {
934 WRITE_REQUEST WriteRequest[2];
935
936 WriteRequest[0].Data = (VOID *) Path;
937 WriteRequest[0].Len = AsciiStrSize (Path);
938 WriteRequest[1].Data = (VOID *) Token;
939 WriteRequest[1].Len = AsciiStrSize (Token);
940
941 return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL);
942 }
943
944 VOID
945 EFIAPI
946 NotifyEventChannelCheckForEvent (
947 IN EFI_EVENT Event,
948 IN VOID *Context
949 )
950 {
951 XENSTORE_PRIVATE *xs;
952 xs = (XENSTORE_PRIVATE *)Context;
953 if (TestAndClearBit (xs->EventChannel, xs->Dev->SharedInfo->evtchn_pending)) {
954 gBS->SignalEvent (Event);
955 }
956 }
957
958 /**
959 Setup communication channels with the XenStore service.
960
961 @retval EFI_SUCCESS if everything went well.
962 **/
963 STATIC
964 EFI_STATUS
965 XenStoreInitComms (
966 XENSTORE_PRIVATE *xs
967 )
968 {
969 EFI_STATUS Status;
970 EFI_EVENT TimerEvent;
971 struct xenstore_domain_interface *XenStore = xs->XenStore;
972
973 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
974 Status = gBS->SetTimer (TimerEvent, TimerRelative,
975 EFI_TIMER_PERIOD_SECONDS (5));
976 while (XenStore->rsp_prod != XenStore->rsp_cons) {
977 Status = gBS->CheckEvent (TimerEvent);
978 if (!EFI_ERROR (Status)) {
979 DEBUG ((EFI_D_WARN, "XENSTORE response ring is not quiescent "
980 "(%08x:%08x): fixing up\n",
981 XenStore->rsp_cons, XenStore->rsp_prod));
982 XenStore->rsp_cons = XenStore->rsp_prod;
983 }
984 }
985 gBS->CloseEvent (TimerEvent);
986
987 Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_NOTIFY,
988 NotifyEventChannelCheckForEvent, xs,
989 &xs->EventChannelEvent);
990 ASSERT_EFI_ERROR (Status);
991
992 return Status;
993 }
994
995 /**
996 Initialize XenStore.
997
998 @param Dev A XENBUS_DEVICE instance.
999
1000 @retval EFI_SUCCESS if everything went well.
1001 **/
1002 EFI_STATUS
1003 XenStoreInit (
1004 XENBUS_DEVICE *Dev
1005 )
1006 {
1007 EFI_STATUS Status;
1008 /**
1009 * The HVM guest pseudo-physical frame number. This is Xen's mapping
1010 * of the true machine frame number into our "physical address space".
1011 */
1012 UINTN XenStoreGpfn;
1013
1014 xs.Dev = Dev;
1015
1016 xs.EventChannel = XenHypercallHvmGetParam (Dev, HVM_PARAM_STORE_EVTCHN);
1017 XenStoreGpfn = XenHypercallHvmGetParam (Dev, HVM_PARAM_STORE_PFN);
1018 xs.XenStore = (VOID *) (XenStoreGpfn << EFI_PAGE_SHIFT);
1019 DEBUG ((EFI_D_INFO, "XenBusInit: XenBus rings @%p, event channel %x\n",
1020 xs.XenStore, xs.EventChannel));
1021
1022 InitializeListHead (&xs.ReplyList);
1023 InitializeListHead (&xs.WatchEvents);
1024 InitializeListHead (&xs.RegisteredWatches);
1025
1026 EfiInitializeLock (&xs.ReplyLock, TPL_NOTIFY);
1027 EfiInitializeLock (&xs.RegisteredWatchesLock, TPL_NOTIFY);
1028 EfiInitializeLock (&xs.WatchEventsLock, TPL_NOTIFY);
1029
1030 /* Initialize the shared memory rings to talk to xenstored */
1031 Status = XenStoreInitComms (&xs);
1032 if (EFI_ERROR (Status)) {
1033 return Status;
1034 }
1035
1036 return Status;
1037 }
1038
1039 VOID
1040 XenStoreDeinit (
1041 IN XENBUS_DEVICE *Dev
1042 )
1043 {
1044 //
1045 // Emptying the list RegisteredWatches, but this list should already be
1046 // empty. Every driver that is using Watches should unregister them when
1047 // it is stopped.
1048 //
1049 if (!IsListEmpty (&xs.RegisteredWatches)) {
1050 XENSTORE_WATCH *Watch;
1051 LIST_ENTRY *Entry;
1052 DEBUG ((EFI_D_WARN, "XenStore: RegisteredWatches is not empty, cleaning up..."));
1053 Entry = GetFirstNode (&xs.RegisteredWatches);
1054 while (!IsNull (&xs.RegisteredWatches, Entry)) {
1055 Watch = XENSTORE_WATCH_FROM_LINK (Entry);
1056 Entry = GetNextNode (&xs.RegisteredWatches, Entry);
1057
1058 XenStoreUnregisterWatch (Watch);
1059 }
1060 }
1061
1062 //
1063 // Emptying the list WatchEvents, but this list should already be empty after
1064 // having cleanup the list RegisteredWatches.
1065 //
1066 if (!IsListEmpty (&xs.WatchEvents)) {
1067 LIST_ENTRY *Entry;
1068 DEBUG ((EFI_D_WARN, "XenStore: WatchEvents is not empty, cleaning up..."));
1069 Entry = GetFirstNode (&xs.WatchEvents);
1070 while (!IsNull (&xs.WatchEvents, Entry)) {
1071 XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
1072 Entry = GetNextNode (&xs.WatchEvents, Entry);
1073 RemoveEntryList (&Message->Link);
1074 FreePool (Message->u.Watch.Vector);
1075 FreePool (Message);
1076 }
1077 }
1078
1079 if (!IsListEmpty (&xs.ReplyList)) {
1080 XENSTORE_MESSAGE *Message;
1081 LIST_ENTRY *Entry;
1082 Entry = GetFirstNode (&xs.ReplyList);
1083 while (!IsNull (&xs.ReplyList, Entry)) {
1084 Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
1085 Entry = GetNextNode (&xs.ReplyList, Entry);
1086 RemoveEntryList (&Message->Link);
1087 FreePool (Message->u.Reply.Body);
1088 FreePool (Message);
1089 }
1090 }
1091
1092 gBS->CloseEvent (xs.EventChannelEvent);
1093
1094 if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) {
1095 xs.XenStore->connection = XENSTORE_RECONNECT;
1096 XenEventChannelNotify (xs.Dev, xs.EventChannel);
1097 while (*(volatile UINT32*)&xs.XenStore->connection == XENSTORE_RECONNECT) {
1098 XenStoreWaitForEvent (xs.EventChannelEvent, EFI_TIMER_PERIOD_MILLISECONDS (100));
1099 }
1100 } else {
1101 /* If the backend reads the state while we're erasing it then the
1102 * ring state will become corrupted, preventing guest frontends from
1103 * connecting. This is rare. To help diagnose the failure, we fill
1104 * the ring with XS_INVALID packets. */
1105 SetMem (xs.XenStore->req, XENSTORE_RING_SIZE, 0xff);
1106 SetMem (xs.XenStore->rsp, XENSTORE_RING_SIZE, 0xff);
1107 xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
1108 xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
1109 }
1110 xs.XenStore = NULL;
1111 }
1112
1113 //
1114 // Public API
1115 // API comments for these methods can be found in XenStore.h
1116 //
1117
1118 XENSTORE_STATUS
1119 XenStoreListDirectory (
1120 IN XENSTORE_TRANSACTION Transaction,
1121 IN CONST CHAR8 *DirectoryPath,
1122 IN CONST CHAR8 *Node,
1123 OUT UINT32 *DirectoryCountPtr,
1124 OUT CONST CHAR8 ***DirectoryListPtr
1125 )
1126 {
1127 CHAR8 *Path;
1128 CHAR8 *TempStr;
1129 UINT32 Len = 0;
1130 XENSTORE_STATUS Status;
1131
1132 Path = XenStoreJoin (DirectoryPath, Node);
1133 Status = XenStoreSingle (Transaction, XS_DIRECTORY, Path, &Len,
1134 (VOID **) &TempStr);
1135 FreePool (Path);
1136 if (Status != XENSTORE_STATUS_SUCCESS) {
1137 return Status;
1138 }
1139
1140 *DirectoryListPtr = Split (TempStr, Len, DirectoryCountPtr);
1141
1142 return XENSTORE_STATUS_SUCCESS;
1143 }
1144
1145 BOOLEAN
1146 XenStorePathExists (
1147 IN XENSTORE_TRANSACTION Transaction,
1148 IN CONST CHAR8 *Directory,
1149 IN CONST CHAR8 *Node
1150 )
1151 {
1152 CONST CHAR8 **TempStr;
1153 XENSTORE_STATUS Status;
1154 UINT32 TempNum;
1155
1156 Status = XenStoreListDirectory (Transaction, Directory, Node,
1157 &TempNum, &TempStr);
1158 if (Status != XENSTORE_STATUS_SUCCESS) {
1159 return FALSE;
1160 }
1161 FreePool (TempStr);
1162 return TRUE;
1163 }
1164
1165 XENSTORE_STATUS
1166 XenStoreRead (
1167 IN XENSTORE_TRANSACTION Transaction,
1168 IN CONST CHAR8 *DirectoryPath,
1169 IN CONST CHAR8 *Node,
1170 OUT UINT32 *LenPtr OPTIONAL,
1171 OUT VOID **Result
1172 )
1173 {
1174 CHAR8 *Path;
1175 VOID *Value;
1176 XENSTORE_STATUS Status;
1177
1178 Path = XenStoreJoin (DirectoryPath, Node);
1179 Status = XenStoreSingle (Transaction, XS_READ, Path, LenPtr, &Value);
1180 FreePool (Path);
1181 if (Status != XENSTORE_STATUS_SUCCESS) {
1182 return Status;
1183 }
1184
1185 *Result = Value;
1186 return XENSTORE_STATUS_SUCCESS;
1187 }
1188
1189 XENSTORE_STATUS
1190 XenStoreWrite (
1191 IN XENSTORE_TRANSACTION Transaction,
1192 IN CONST CHAR8 *DirectoryPath,
1193 IN CONST CHAR8 *Node,
1194 IN CONST CHAR8 *Str
1195 )
1196 {
1197 CHAR8 *Path;
1198 WRITE_REQUEST WriteRequest[2];
1199 XENSTORE_STATUS Status;
1200
1201 Path = XenStoreJoin (DirectoryPath, Node);
1202
1203 WriteRequest[0].Data = (VOID *) Path;
1204 WriteRequest[0].Len = AsciiStrSize (Path);
1205 WriteRequest[1].Data = (VOID *) Str;
1206 WriteRequest[1].Len = AsciiStrLen (Str);
1207
1208 Status = XenStoreTalkv (Transaction, XS_WRITE, WriteRequest, 2, NULL, NULL);
1209 FreePool (Path);
1210
1211 return Status;
1212 }
1213
1214 XENSTORE_STATUS
1215 XenStoreRemove (
1216 IN XENSTORE_TRANSACTION Transaction,
1217 IN CONST CHAR8 *DirectoryPath,
1218 IN CONST CHAR8 *Node
1219 )
1220 {
1221 CHAR8 *Path;
1222 XENSTORE_STATUS Status;
1223
1224 Path = XenStoreJoin (DirectoryPath, Node);
1225 Status = XenStoreSingle (Transaction, XS_RM, Path, NULL, NULL);
1226 FreePool (Path);
1227
1228 return Status;
1229 }
1230
1231 XENSTORE_STATUS
1232 XenStoreTransactionStart (
1233 OUT XENSTORE_TRANSACTION *Transaction
1234 )
1235 {
1236 CHAR8 *IdStr;
1237 XENSTORE_STATUS Status;
1238
1239 Status = XenStoreSingle (XST_NIL, XS_TRANSACTION_START, "", NULL,
1240 (VOID **) &IdStr);
1241 if (Status == XENSTORE_STATUS_SUCCESS) {
1242 Transaction->Id = AsciiStrDecimalToUintn (IdStr);
1243 FreePool (IdStr);
1244 }
1245
1246 return Status;
1247 }
1248
1249 XENSTORE_STATUS
1250 XenStoreTransactionEnd (
1251 IN XENSTORE_TRANSACTION Transaction,
1252 IN BOOLEAN Abort
1253 )
1254 {
1255 CHAR8 AbortStr[2];
1256
1257 if (Abort) {
1258 AsciiStrCpy (AbortStr, "F");
1259 } else {
1260 AsciiStrCpy (AbortStr, "T");
1261 }
1262
1263 return XenStoreSingle (Transaction, XS_TRANSACTION_END, AbortStr, NULL, NULL);
1264 }
1265
1266 XENSTORE_STATUS
1267 XenStoreVSPrint (
1268 IN XENSTORE_TRANSACTION Transaction,
1269 IN CONST CHAR8 *DirectoryPath,
1270 IN CONST CHAR8 *Node,
1271 IN CONST CHAR8 *FormatString,
1272 IN VA_LIST Marker
1273 )
1274 {
1275 CHAR8 *Buf;
1276 XENSTORE_STATUS Status;
1277 UINTN BufSize;
1278
1279 BufSize = SPrintLengthAsciiFormat (FormatString, Marker) + 1;
1280 Buf = AllocateZeroPool (BufSize);
1281 AsciiVSPrint (Buf, BufSize, FormatString, Marker);
1282 Status = XenStoreWrite (Transaction, DirectoryPath, Node, Buf);
1283 FreePool (Buf);
1284
1285 return Status;
1286 }
1287
1288 XENSTORE_STATUS
1289 EFIAPI
1290 XenStoreSPrint (
1291 IN XENSTORE_TRANSACTION Transaction,
1292 IN CONST CHAR8 *DirectoryPath,
1293 IN CONST CHAR8 *Node,
1294 IN CONST CHAR8 *FormatString,
1295 ...
1296 )
1297 {
1298 VA_LIST Marker;
1299 XENSTORE_STATUS Status;
1300
1301 VA_START (Marker, FormatString);
1302 Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker);
1303 VA_END (Marker);
1304
1305 return Status;
1306 }
1307
1308 XENSTORE_STATUS
1309 XenStoreRegisterWatch (
1310 IN CONST CHAR8 *DirectoryPath,
1311 IN CONST CHAR8 *Node,
1312 OUT XENSTORE_WATCH **WatchPtr
1313 )
1314 {
1315 /* Pointer in ascii is the token. */
1316 CHAR8 Token[sizeof (XENSTORE_WATCH) * 2 + 1];
1317 XENSTORE_STATUS Status;
1318 XENSTORE_WATCH *Watch;
1319
1320 Watch = AllocateZeroPool (sizeof (XENSTORE_WATCH));
1321 Watch->Signature = XENSTORE_WATCH_SIGNATURE;
1322 Watch->Node = XenStoreJoin (DirectoryPath, Node);
1323
1324 EfiAcquireLock (&xs.RegisteredWatchesLock);
1325 InsertTailList (&xs.RegisteredWatches, &Watch->Link);
1326 EfiReleaseLock (&xs.RegisteredWatchesLock);
1327
1328 AsciiSPrint (Token, sizeof (Token), "%p", (VOID*) Watch);
1329 Status = XenStoreWatch (Watch->Node, Token);
1330
1331 /* Ignore errors due to multiple registration. */
1332 if (Status == XENSTORE_STATUS_EEXIST) {
1333 Status = XENSTORE_STATUS_SUCCESS;
1334 }
1335
1336 if (Status == XENSTORE_STATUS_SUCCESS) {
1337 *WatchPtr = Watch;
1338 } else {
1339 EfiAcquireLock (&xs.RegisteredWatchesLock);
1340 RemoveEntryList (&Watch->Link);
1341 EfiReleaseLock (&xs.RegisteredWatchesLock);
1342 FreePool (Watch->Node);
1343 FreePool (Watch);
1344 }
1345
1346 return Status;
1347 }
1348
1349 VOID
1350 XenStoreUnregisterWatch (
1351 IN XENSTORE_WATCH *Watch
1352 )
1353 {
1354 CHAR8 Token[sizeof (Watch) * 2 + 1];
1355 LIST_ENTRY *Entry;
1356
1357 ASSERT (Watch->Signature == XENSTORE_WATCH_SIGNATURE);
1358
1359 AsciiSPrint (Token, sizeof (Token), "%p", (VOID *) Watch);
1360 if (XenStoreFindWatch (Token) == NULL) {
1361 return;
1362 }
1363
1364 EfiAcquireLock (&xs.RegisteredWatchesLock);
1365 RemoveEntryList (&Watch->Link);
1366 EfiReleaseLock (&xs.RegisteredWatchesLock);
1367
1368 XenStoreUnwatch (Watch->Node, Token);
1369
1370 /* Cancel pending watch events. */
1371 EfiAcquireLock (&xs.WatchEventsLock);
1372 Entry = GetFirstNode (&xs.WatchEvents);
1373 while (!IsNull (&xs.WatchEvents, Entry)) {
1374 XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
1375 Entry = GetNextNode (&xs.WatchEvents, Entry);
1376 if (Message->u.Watch.Handle == Watch) {
1377 RemoveEntryList (&Message->Link);
1378 FreePool (Message->u.Watch.Vector);
1379 FreePool (Message);
1380 }
1381 }
1382 EfiReleaseLock (&xs.WatchEventsLock);
1383
1384 FreePool (Watch->Node);
1385 FreePool (Watch);
1386 }