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 717 STATIC 718 XENSTORE_STATUS 719 XenStoreGetError ( 720 CONST CHAR8 *ErrorStr 721 ) 722 { 723 UINT32 Index; 724 725 for (Index = 0; Index < ARRAY_SIZE(gXenStoreErrors); Index++) { 726 if (!AsciiStrCmp (ErrorStr, gXenStoreErrors[Index].ErrorStr)) { 727 return gXenStoreErrors[Index].Status; 728 } 729 } 730 DEBUG ((EFI_D_WARN, "XenStore gave unknown error %a\n", ErrorStr)); 731 return XENSTORE_STATUS_EINVAL; 732 } 733 734 /** 735 Block waiting for a reply to a message request. 736 737 @param TypePtr The returned type of the reply. 738 @param LenPtr The returned body length of the reply. 739 @param Result The returned body of the reply. 740 **/ 741 STATIC 742 XENSTORE_STATUS 743 XenStoreReadReply ( 744 OUT enum xsd_sockmsg_type *TypePtr, 745 OUT UINT32 *LenPtr OPTIONAL, 746 OUT VOID **Result 747 ) 748 { 749 XENSTORE_MESSAGE *Message; 750 LIST_ENTRY *Entry; 751 CHAR8 *Body; 752 753 while (IsListEmpty (&xs.ReplyList)) { 754 XENSTORE_STATUS Status; 755 Status = XenStoreProcessMessage (); 756 if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) { 757 DEBUG ((EFI_D_ERROR, "XenStore, error while reading the ring (%d).", 758 Status)); 759 return Status; 760 } 761 } 762 EfiAcquireLock (&xs.ReplyLock); 763 Entry = GetFirstNode (&xs.ReplyList); 764 Message = XENSTORE_MESSAGE_FROM_LINK (Entry); 765 RemoveEntryList (Entry); 766 EfiReleaseLock (&xs.ReplyLock); 767 768 *TypePtr = Message->Header.type; 769 if (LenPtr != NULL) { 770 *LenPtr = Message->Header.len; 771 } 772 Body = Message->u.Reply.Body; 773 774 FreePool (Message); 775 *Result = Body; 776 return XENSTORE_STATUS_SUCCESS; 777 } 778 779 /** 780 Send a message with an optionally muti-part body to the XenStore service. 781 782 @param Transaction The transaction to use for this request. 783 @param RequestType The type of message to send. 784 @param WriteRequest Pointers to the body sections of the request. 785 @param NumRequests The number of body sections in the request. 786 @param LenPtr The returned length of the reply. 787 @param ResultPtr The returned body of the reply. 788 789 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating 790 the cause of failure. 791 **/ 792 STATIC 793 XENSTORE_STATUS 794 XenStoreTalkv ( 795 IN CONST XENSTORE_TRANSACTION *Transaction, 796 IN enum xsd_sockmsg_type RequestType, 797 IN CONST WRITE_REQUEST *WriteRequest, 798 IN UINT32 NumRequests, 799 OUT UINT32 *LenPtr OPTIONAL, 800 OUT VOID **ResultPtr OPTIONAL 801 ) 802 { 803 struct xsd_sockmsg Message; 804 void *Return = NULL; 805 UINT32 Index; 806 XENSTORE_STATUS Status; 807 808 if (Transaction == XST_NIL) { 809 Message.tx_id = 0; 810 } else { 811 Message.tx_id = Transaction->Id; 812 } 813 Message.req_id = 0; 814 Message.type = RequestType; 815 Message.len = 0; 816 for (Index = 0; Index < NumRequests; Index++) { 817 Message.len += WriteRequest[Index].Len; 818 } 819 820 Status = XenStoreWriteStore (&Message, sizeof (Message)); 821 if (Status != XENSTORE_STATUS_SUCCESS) { 822 DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status)); 823 goto Error; 824 } 825 826 for (Index = 0; Index < NumRequests; Index++) { 827 Status = XenStoreWriteStore (WriteRequest[Index].Data, WriteRequest[Index].Len); 828 if (Status != XENSTORE_STATUS_SUCCESS) { 829 DEBUG ((EFI_D_ERROR, "XenStoreTalkv failed %d\n", Status)); 830 goto Error; 831 } 832 } 833 834 Status = XenStoreReadReply ((enum xsd_sockmsg_type *)&Message.type, LenPtr, &Return); 835 836 Error: 837 if (Status != XENSTORE_STATUS_SUCCESS) { 838 return Status; 839 } 840 841 if (Message.type == XS_ERROR) { 842 Status = XenStoreGetError (Return); 843 FreePool (Return); 844 return Status; 845 } 846 847 /* Reply is either error or an echo of our request message type. */ 848 ASSERT ((enum xsd_sockmsg_type)Message.type == RequestType); 849 850 if (ResultPtr) { 851 *ResultPtr = Return; 852 } else { 853 FreePool (Return); 854 } 855 856 return XENSTORE_STATUS_SUCCESS; 857 } 858 859 /** 860 Wrapper for XenStoreTalkv allowing easy transmission of a message with 861 a single, contiguous, message body. 862 863 The returned result is provided in malloced storage and thus must be free'd 864 by the caller. 865 866 @param Transaction The transaction to use for this request. 867 @param RequestType The type of message to send. 868 @param Body The body of the request. 869 @param LenPtr The returned length of the reply. 870 @param Result The returned body of the reply. 871 872 @return 0 on success. Otherwise an errno indicating 873 the cause of failure. 874 **/ 875 STATIC 876 XENSTORE_STATUS 877 XenStoreSingle ( 878 IN CONST XENSTORE_TRANSACTION *Transaction, 879 IN enum xsd_sockmsg_type RequestType, 880 IN CONST CHAR8 *Body, 881 OUT UINT32 *LenPtr OPTIONAL, 882 OUT VOID **Result OPTIONAL 883 ) 884 { 885 WRITE_REQUEST WriteRequest; 886 887 WriteRequest.Data = (VOID *) Body; 888 WriteRequest.Len = (UINT32)AsciiStrSize (Body); 889 890 return XenStoreTalkv (Transaction, RequestType, &WriteRequest, 1, 891 LenPtr, Result); 892 } 893 894 // 895 // XenStore Watch Support 896 // 897 898 /** 899 Transmit a watch request to the XenStore service. 900 901 @param Path The path in the XenStore to watch. 902 @param Tocken A unique identifier for this watch. 903 904 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating the 905 cause of failure. 906 **/ 907 STATIC 908 XENSTORE_STATUS 909 XenStoreWatch ( 910 CONST CHAR8 *Path, 911 CONST CHAR8 *Token 912 ) 913 { 914 WRITE_REQUEST WriteRequest[2]; 915 916 WriteRequest[0].Data = (VOID *) Path; 917 WriteRequest[0].Len = (UINT32)AsciiStrSize (Path); 918 WriteRequest[1].Data = (VOID *) Token; 919 WriteRequest[1].Len = (UINT32)AsciiStrSize (Token); 920 921 return XenStoreTalkv (XST_NIL, XS_WATCH, WriteRequest, 2, NULL, NULL); 922 } 923 924 /** 925 Transmit an uwatch request to the XenStore service. 926 927 @param Path The path in the XenStore to watch. 928 @param Tocken A unique identifier for this watch. 929 930 @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating 931 the cause of failure. 932 **/ 933 STATIC 934 XENSTORE_STATUS 935 XenStoreUnwatch ( 936 CONST CHAR8 *Path, 937 CONST CHAR8 *Token 938 ) 939 { 940 WRITE_REQUEST WriteRequest[2]; 941 942 WriteRequest[0].Data = (VOID *) Path; 943 WriteRequest[0].Len = (UINT32)AsciiStrSize (Path); 944 WriteRequest[1].Data = (VOID *) Token; 945 WriteRequest[1].Len = (UINT32)AsciiStrSize (Token); 946 947 return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL); 948 } 949 950 STATIC 951 XENSTORE_STATUS 952 XenStoreWaitWatch ( 953 VOID *Token 954 ) 955 { 956 XENSTORE_MESSAGE *Message; 957 LIST_ENTRY *Entry = NULL; 958 LIST_ENTRY *Last = NULL; 959 XENSTORE_STATUS Status; 960 961 while (TRUE) { 962 EfiAcquireLock (&xs.WatchEventsLock); 963 if (IsListEmpty (&xs.WatchEvents) || 964 Last == GetFirstNode (&xs.WatchEvents)) { 965 EfiReleaseLock (&xs.WatchEventsLock); 966 Status = XenStoreProcessMessage (); 967 if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) { 968 return Status; 969 } 970 continue; 971 } 972 973 for (Entry = GetFirstNode (&xs.WatchEvents); 974 Entry != Last && !IsNull (&xs.WatchEvents, Entry); 975 Entry = GetNextNode (&xs.WatchEvents, Entry)) { 976 Message = XENSTORE_MESSAGE_FROM_LINK (Entry); 977 if (Message->u.Watch.Handle == Token) { 978 RemoveEntryList (Entry); 979 EfiReleaseLock (&xs.WatchEventsLock); 980 FreePool((VOID*)Message->u.Watch.Vector); 981 FreePool(Message); 982 return XENSTORE_STATUS_SUCCESS; 983 } 984 } 985 Last = GetFirstNode (&xs.WatchEvents); 986 EfiReleaseLock (&xs.WatchEventsLock); 987 } 988 } 989 990 VOID 991 EFIAPI 992 NotifyEventChannelCheckForEvent ( 993 IN EFI_EVENT Event, 994 IN VOID *Context 995 ) 996 { 997 XENSTORE_PRIVATE *xsp; 998 xsp = (XENSTORE_PRIVATE *)Context; 999 if (TestAndClearBit (xsp->EventChannel, xsp->Dev->SharedInfo->evtchn_pending)) { 1000 gBS->SignalEvent (Event); 1001 } 1002 } 1003 1004 /** 1005 Setup communication channels with the XenStore service. 1006 1007 @retval EFI_SUCCESS if everything went well. 1008 **/ 1009 STATIC 1010 EFI_STATUS 1011 XenStoreInitComms ( 1012 XENSTORE_PRIVATE *xsp 1013 ) 1014 { 1015 EFI_STATUS Status; 1016 EFI_EVENT TimerEvent; 1017 struct xenstore_domain_interface *XenStore = xsp->XenStore; 1018 1019 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent); 1020 Status = gBS->SetTimer (TimerEvent, TimerRelative, 1021 EFI_TIMER_PERIOD_SECONDS (5)); 1022 while (XenStore->rsp_prod != XenStore->rsp_cons) { 1023 Status = gBS->CheckEvent (TimerEvent); 1024 if (!EFI_ERROR (Status)) { 1025 DEBUG ((EFI_D_WARN, "XENSTORE response ring is not quiescent " 1026 "(%08x:%08x): fixing up\n", 1027 XenStore->rsp_cons, XenStore->rsp_prod)); 1028 XenStore->rsp_cons = XenStore->rsp_prod; 1029 } 1030 } 1031 gBS->CloseEvent (TimerEvent); 1032 1033 Status = gBS->CreateEvent (EVT_NOTIFY_WAIT, TPL_NOTIFY, 1034 NotifyEventChannelCheckForEvent, xsp, 1035 &xsp->EventChannelEvent); 1036 ASSERT_EFI_ERROR (Status); 1037 1038 return Status; 1039 } 1040 1041 /** 1042 Initialize XenStore. 1043 1044 @param Dev A XENBUS_DEVICE instance. 1045 1046 @retval EFI_SUCCESS if everything went well. 1047 **/ 1048 EFI_STATUS 1049 XenStoreInit ( 1050 XENBUS_DEVICE *Dev 1051 ) 1052 { 1053 EFI_STATUS Status; 1054 /** 1055 * The HVM guest pseudo-physical frame number. This is Xen's mapping 1056 * of the true machine frame number into our "physical address space". 1057 */ 1058 UINTN XenStoreGpfn; 1059 1060 xs.Dev = Dev; 1061 1062 xs.EventChannel = (evtchn_port_t)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN); 1063 XenStoreGpfn = (UINTN)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN); 1064 xs.XenStore = (VOID *) (XenStoreGpfn << EFI_PAGE_SHIFT); 1065 DEBUG ((EFI_D_INFO, "XenBusInit: XenBus rings @%p, event channel %x\n", 1066 xs.XenStore, xs.EventChannel)); 1067 1068 InitializeListHead (&xs.ReplyList); 1069 InitializeListHead (&xs.WatchEvents); 1070 InitializeListHead (&xs.RegisteredWatches); 1071 1072 EfiInitializeLock (&xs.ReplyLock, TPL_NOTIFY); 1073 EfiInitializeLock (&xs.RegisteredWatchesLock, TPL_NOTIFY); 1074 EfiInitializeLock (&xs.WatchEventsLock, TPL_NOTIFY); 1075 1076 /* Initialize the shared memory rings to talk to xenstored */ 1077 Status = XenStoreInitComms (&xs); 1078 if (EFI_ERROR (Status)) { 1079 return Status; 1080 } 1081 1082 return Status; 1083 } 1084 1085 VOID 1086 XenStoreDeinit ( 1087 IN XENBUS_DEVICE *Dev 1088 ) 1089 { 1090 // 1091 // Emptying the list RegisteredWatches, but this list should already be 1092 // empty. Every driver that is using Watches should unregister them when 1093 // it is stopped. 1094 // 1095 if (!IsListEmpty (&xs.RegisteredWatches)) { 1096 XENSTORE_WATCH *Watch; 1097 LIST_ENTRY *Entry; 1098 DEBUG ((EFI_D_WARN, "XenStore: RegisteredWatches is not empty, cleaning up...")); 1099 Entry = GetFirstNode (&xs.RegisteredWatches); 1100 while (!IsNull (&xs.RegisteredWatches, Entry)) { 1101 Watch = XENSTORE_WATCH_FROM_LINK (Entry); 1102 Entry = GetNextNode (&xs.RegisteredWatches, Entry); 1103 1104 XenStoreUnregisterWatch (Watch); 1105 } 1106 } 1107 1108 // 1109 // Emptying the list WatchEvents, but this list should already be empty after 1110 // having cleanup the list RegisteredWatches. 1111 // 1112 if (!IsListEmpty (&xs.WatchEvents)) { 1113 LIST_ENTRY *Entry; 1114 DEBUG ((EFI_D_WARN, "XenStore: WatchEvents is not empty, cleaning up...")); 1115 Entry = GetFirstNode (&xs.WatchEvents); 1116 while (!IsNull (&xs.WatchEvents, Entry)) { 1117 XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry); 1118 Entry = GetNextNode (&xs.WatchEvents, Entry); 1119 RemoveEntryList (&Message->Link); 1120 FreePool ((VOID*)Message->u.Watch.Vector); 1121 FreePool (Message); 1122 } 1123 } 1124 1125 if (!IsListEmpty (&xs.ReplyList)) { 1126 XENSTORE_MESSAGE *Message; 1127 LIST_ENTRY *Entry; 1128 Entry = GetFirstNode (&xs.ReplyList); 1129 while (!IsNull (&xs.ReplyList, Entry)) { 1130 Message = XENSTORE_MESSAGE_FROM_LINK (Entry); 1131 Entry = GetNextNode (&xs.ReplyList, Entry); 1132 RemoveEntryList (&Message->Link); 1133 FreePool (Message->u.Reply.Body); 1134 FreePool (Message); 1135 } 1136 } 1137 1138 gBS->CloseEvent (xs.EventChannelEvent); 1139 1140 if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) { 1141 xs.XenStore->connection = XENSTORE_RECONNECT; 1142 XenEventChannelNotify (xs.Dev, xs.EventChannel); 1143 while (*(volatile UINT32*)&xs.XenStore->connection == XENSTORE_RECONNECT) { 1144 XenStoreWaitForEvent (xs.EventChannelEvent, EFI_TIMER_PERIOD_MILLISECONDS (100)); 1145 } 1146 } else { 1147 /* If the backend reads the state while we're erasing it then the 1148 * ring state will become corrupted, preventing guest frontends from 1149 * connecting. This is rare. To help diagnose the failure, we fill 1150 * the ring with XS_INVALID packets. */ 1151 SetMem (xs.XenStore->req, XENSTORE_RING_SIZE, 0xff); 1152 SetMem (xs.XenStore->rsp, XENSTORE_RING_SIZE, 0xff); 1153 xs.XenStore->req_cons = xs.XenStore->req_prod = 0; 1154 xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0; 1155 } 1156 xs.XenStore = NULL; 1157 } 1158 1159 // 1160 // Public API 1161 // API comments for these methods can be found in XenStore.h 1162 // 1163 1164 XENSTORE_STATUS 1165 XenStoreListDirectory ( 1166 IN CONST XENSTORE_TRANSACTION *Transaction, 1167 IN CONST CHAR8 *DirectoryPath, 1168 IN CONST CHAR8 *Node, 1169 OUT UINT32 *DirectoryCountPtr, 1170 OUT CONST CHAR8 ***DirectoryListPtr 1171 ) 1172 { 1173 CHAR8 *Path; 1174 CHAR8 *TempStr; 1175 UINT32 Len = 0; 1176 XENSTORE_STATUS Status; 1177 1178 Path = XenStoreJoin (DirectoryPath, Node); 1179 Status = XenStoreSingle (Transaction, XS_DIRECTORY, Path, &Len, 1180 (VOID **) &TempStr); 1181 FreePool (Path); 1182 if (Status != XENSTORE_STATUS_SUCCESS) { 1183 return Status; 1184 } 1185 1186 *DirectoryListPtr = Split (TempStr, Len, DirectoryCountPtr); 1187 1188 return XENSTORE_STATUS_SUCCESS; 1189 } 1190 1191 BOOLEAN 1192 XenStorePathExists ( 1193 IN CONST XENSTORE_TRANSACTION *Transaction, 1194 IN CONST CHAR8 *Directory, 1195 IN CONST CHAR8 *Node 1196 ) 1197 { 1198 CONST CHAR8 **TempStr; 1199 XENSTORE_STATUS Status; 1200 UINT32 TempNum; 1201 1202 Status = XenStoreListDirectory (Transaction, Directory, Node, 1203 &TempNum, &TempStr); 1204 if (Status != XENSTORE_STATUS_SUCCESS) { 1205 return FALSE; 1206 } 1207 FreePool ((VOID*)TempStr); 1208 return TRUE; 1209 } 1210 1211 XENSTORE_STATUS 1212 XenStoreRead ( 1213 IN CONST XENSTORE_TRANSACTION *Transaction, 1214 IN CONST CHAR8 *DirectoryPath, 1215 IN CONST CHAR8 *Node, 1216 OUT UINT32 *LenPtr OPTIONAL, 1217 OUT VOID **Result 1218 ) 1219 { 1220 CHAR8 *Path; 1221 VOID *Value; 1222 XENSTORE_STATUS Status; 1223 1224 Path = XenStoreJoin (DirectoryPath, Node); 1225 Status = XenStoreSingle (Transaction, XS_READ, Path, LenPtr, &Value); 1226 FreePool (Path); 1227 if (Status != XENSTORE_STATUS_SUCCESS) { 1228 return Status; 1229 } 1230 1231 *Result = Value; 1232 return XENSTORE_STATUS_SUCCESS; 1233 } 1234 1235 XENSTORE_STATUS 1236 XenStoreWrite ( 1237 IN CONST XENSTORE_TRANSACTION *Transaction, 1238 IN CONST CHAR8 *DirectoryPath, 1239 IN CONST CHAR8 *Node, 1240 IN CONST CHAR8 *Str 1241 ) 1242 { 1243 CHAR8 *Path; 1244 WRITE_REQUEST WriteRequest[2]; 1245 XENSTORE_STATUS Status; 1246 1247 Path = XenStoreJoin (DirectoryPath, Node); 1248 1249 WriteRequest[0].Data = (VOID *) Path; 1250 WriteRequest[0].Len = (UINT32)AsciiStrSize (Path); 1251 WriteRequest[1].Data = (VOID *) Str; 1252 WriteRequest[1].Len = (UINT32)AsciiStrLen (Str); 1253 1254 Status = XenStoreTalkv (Transaction, XS_WRITE, WriteRequest, 2, NULL, NULL); 1255 FreePool (Path); 1256 1257 return Status; 1258 } 1259 1260 XENSTORE_STATUS 1261 XenStoreRemove ( 1262 IN CONST XENSTORE_TRANSACTION *Transaction, 1263 IN CONST CHAR8 *DirectoryPath, 1264 IN CONST CHAR8 *Node 1265 ) 1266 { 1267 CHAR8 *Path; 1268 XENSTORE_STATUS Status; 1269 1270 Path = XenStoreJoin (DirectoryPath, Node); 1271 Status = XenStoreSingle (Transaction, XS_RM, Path, NULL, NULL); 1272 FreePool (Path); 1273 1274 return Status; 1275 } 1276 1277 XENSTORE_STATUS 1278 XenStoreTransactionStart ( 1279 OUT XENSTORE_TRANSACTION *Transaction 1280 ) 1281 { 1282 CHAR8 *IdStr; 1283 XENSTORE_STATUS Status; 1284 1285 Status = XenStoreSingle (XST_NIL, XS_TRANSACTION_START, "", NULL, 1286 (VOID **) &IdStr); 1287 if (Status == XENSTORE_STATUS_SUCCESS) { 1288 Transaction->Id = (UINT32)AsciiStrDecimalToUintn (IdStr); 1289 FreePool (IdStr); 1290 } 1291 1292 return Status; 1293 } 1294 1295 XENSTORE_STATUS 1296 XenStoreTransactionEnd ( 1297 IN CONST XENSTORE_TRANSACTION *Transaction, 1298 IN BOOLEAN Abort 1299 ) 1300 { 1301 CHAR8 AbortStr[2]; 1302 1303 AbortStr[0] = Abort ? 'F' : 'T'; 1304 AbortStr[1] = '\0'; 1305 1306 return XenStoreSingle (Transaction, XS_TRANSACTION_END, AbortStr, NULL, NULL); 1307 } 1308 1309 XENSTORE_STATUS 1310 XenStoreVSPrint ( 1311 IN CONST XENSTORE_TRANSACTION *Transaction, 1312 IN CONST CHAR8 *DirectoryPath, 1313 IN CONST CHAR8 *Node, 1314 IN CONST CHAR8 *FormatString, 1315 IN VA_LIST Marker 1316 ) 1317 { 1318 CHAR8 *Buf; 1319 XENSTORE_STATUS Status; 1320 UINTN BufSize; 1321 VA_LIST Marker2; 1322 1323 VA_COPY (Marker2, Marker); 1324 BufSize = SPrintLengthAsciiFormat (FormatString, Marker2) + 1; 1325 VA_END (Marker2); 1326 Buf = AllocateZeroPool (BufSize); 1327 AsciiVSPrint (Buf, BufSize, FormatString, Marker); 1328 Status = XenStoreWrite (Transaction, DirectoryPath, Node, Buf); 1329 FreePool (Buf); 1330 1331 return Status; 1332 } 1333 1334 XENSTORE_STATUS 1335 EFIAPI 1336 XenStoreSPrint ( 1337 IN CONST XENSTORE_TRANSACTION *Transaction, 1338 IN CONST CHAR8 *DirectoryPath, 1339 IN CONST CHAR8 *Node, 1340 IN CONST CHAR8 *FormatString, 1341 ... 1342 ) 1343 { 1344 VA_LIST Marker; 1345 XENSTORE_STATUS Status; 1346 1347 VA_START (Marker, FormatString); 1348 Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker); 1349 VA_END (Marker); 1350 1351 return Status; 1352 } 1353 1354 XENSTORE_STATUS 1355 XenStoreRegisterWatch ( 1356 IN CONST CHAR8 *DirectoryPath, 1357 IN CONST CHAR8 *Node, 1358 OUT XENSTORE_WATCH **WatchPtr 1359 ) 1360 { 1361 /* Pointer in ascii is the token. */ 1362 CHAR8 Token[sizeof (XENSTORE_WATCH) * 2 + 1]; 1363 XENSTORE_STATUS Status; 1364 XENSTORE_WATCH *Watch; 1365 1366 Watch = AllocateZeroPool (sizeof (XENSTORE_WATCH)); 1367 Watch->Signature = XENSTORE_WATCH_SIGNATURE; 1368 Watch->Node = XenStoreJoin (DirectoryPath, Node); 1369 1370 EfiAcquireLock (&xs.RegisteredWatchesLock); 1371 InsertTailList (&xs.RegisteredWatches, &Watch->Link); 1372 EfiReleaseLock (&xs.RegisteredWatchesLock); 1373 1374 AsciiSPrint (Token, sizeof (Token), "%p", (VOID*) Watch); 1375 Status = XenStoreWatch (Watch->Node, Token); 1376 1377 /* Ignore errors due to multiple registration. */ 1378 if (Status == XENSTORE_STATUS_EEXIST) { 1379 Status = XENSTORE_STATUS_SUCCESS; 1380 } 1381 1382 if (Status == XENSTORE_STATUS_SUCCESS) { 1383 *WatchPtr = Watch; 1384 } else { 1385 EfiAcquireLock (&xs.RegisteredWatchesLock); 1386 RemoveEntryList (&Watch->Link); 1387 EfiReleaseLock (&xs.RegisteredWatchesLock); 1388 FreePool (Watch->Node); 1389 FreePool (Watch); 1390 } 1391 1392 return Status; 1393 } 1394 1395 VOID 1396 XenStoreUnregisterWatch ( 1397 IN XENSTORE_WATCH *Watch 1398 ) 1399 { 1400 CHAR8 Token[sizeof (Watch) * 2 + 1]; 1401 LIST_ENTRY *Entry; 1402 1403 ASSERT (Watch->Signature == XENSTORE_WATCH_SIGNATURE); 1404 1405 AsciiSPrint (Token, sizeof (Token), "%p", (VOID *) Watch); 1406 if (XenStoreFindWatch (Token) == NULL) { 1407 return; 1408 } 1409 1410 EfiAcquireLock (&xs.RegisteredWatchesLock); 1411 RemoveEntryList (&Watch->Link); 1412 EfiReleaseLock (&xs.RegisteredWatchesLock); 1413 1414 XenStoreUnwatch (Watch->Node, Token); 1415 1416 /* Cancel pending watch events. */ 1417 EfiAcquireLock (&xs.WatchEventsLock); 1418 Entry = GetFirstNode (&xs.WatchEvents); 1419 while (!IsNull (&xs.WatchEvents, Entry)) { 1420 XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry); 1421 Entry = GetNextNode (&xs.WatchEvents, Entry); 1422 if (Message->u.Watch.Handle == Watch) { 1423 RemoveEntryList (&Message->Link); 1424 FreePool ((VOID*)Message->u.Watch.Vector); 1425 FreePool (Message); 1426 } 1427 } 1428 EfiReleaseLock (&xs.WatchEventsLock); 1429 1430 FreePool (Watch->Node); 1431 FreePool (Watch); 1432 } 1433 1434 1435 // 1436 // XENBUS protocol 1437 // 1438 1439 XENSTORE_STATUS 1440 EFIAPI 1441 XenBusWaitForWatch ( 1442 IN XENBUS_PROTOCOL *This, 1443 IN VOID *Token 1444 ) 1445 { 1446 return XenStoreWaitWatch (Token); 1447 } 1448 1449 XENSTORE_STATUS 1450 EFIAPI 1451 XenBusXenStoreRead ( 1452 IN XENBUS_PROTOCOL *This, 1453 IN CONST XENSTORE_TRANSACTION *Transaction, 1454 IN CONST CHAR8 *Node, 1455 OUT VOID **Value 1456 ) 1457 { 1458 return XenStoreRead (Transaction, This->Node, Node, NULL, Value); 1459 } 1460 1461 XENSTORE_STATUS 1462 EFIAPI 1463 XenBusXenStoreBackendRead ( 1464 IN XENBUS_PROTOCOL *This, 1465 IN CONST XENSTORE_TRANSACTION *Transaction, 1466 IN CONST CHAR8 *Node, 1467 OUT VOID **Value 1468 ) 1469 { 1470 return XenStoreRead (Transaction, This->Backend, Node, NULL, Value); 1471 } 1472 1473 XENSTORE_STATUS 1474 EFIAPI 1475 XenBusXenStoreRemove ( 1476 IN XENBUS_PROTOCOL *This, 1477 IN CONST XENSTORE_TRANSACTION *Transaction, 1478 IN const char *Node 1479 ) 1480 { 1481 return XenStoreRemove (Transaction, This->Node, Node); 1482 } 1483 1484 XENSTORE_STATUS 1485 EFIAPI 1486 XenBusXenStoreTransactionStart ( 1487 IN XENBUS_PROTOCOL *This, 1488 OUT XENSTORE_TRANSACTION *Transaction 1489 ) 1490 { 1491 return XenStoreTransactionStart (Transaction); 1492 } 1493 1494 XENSTORE_STATUS 1495 EFIAPI 1496 XenBusXenStoreTransactionEnd ( 1497 IN XENBUS_PROTOCOL *This, 1498 IN CONST XENSTORE_TRANSACTION *Transaction, 1499 IN BOOLEAN Abort 1500 ) 1501 { 1502 return XenStoreTransactionEnd (Transaction, Abort); 1503 } 1504 1505 XENSTORE_STATUS 1506 EFIAPI 1507 XenBusXenStoreSPrint ( 1508 IN XENBUS_PROTOCOL *This, 1509 IN CONST XENSTORE_TRANSACTION *Transaction, 1510 IN CONST CHAR8 *DirectoryPath, 1511 IN CONST CHAR8 *Node, 1512 IN CONST CHAR8 *FormatString, 1513 ... 1514 ) 1515 { 1516 VA_LIST Marker; 1517 XENSTORE_STATUS Status; 1518 1519 VA_START (Marker, FormatString); 1520 Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker); 1521 VA_END (Marker); 1522 1523 return Status; 1524 } 1525 1526 XENSTORE_STATUS 1527 EFIAPI 1528 XenBusRegisterWatch ( 1529 IN XENBUS_PROTOCOL *This, 1530 IN CONST CHAR8 *Node, 1531 OUT VOID **Token 1532 ) 1533 { 1534 return XenStoreRegisterWatch (This->Node, Node, (XENSTORE_WATCH **) Token); 1535 } 1536 1537 XENSTORE_STATUS 1538 EFIAPI 1539 XenBusRegisterWatchBackend ( 1540 IN XENBUS_PROTOCOL *This, 1541 IN CONST CHAR8 *Node, 1542 OUT VOID **Token 1543 ) 1544 { 1545 return XenStoreRegisterWatch (This->Backend, Node, (XENSTORE_WATCH **) Token); 1546 } 1547 1548 VOID 1549 EFIAPI 1550 XenBusUnregisterWatch ( 1551 IN XENBUS_PROTOCOL *This, 1552 IN VOID *Token 1553 ) 1554 { 1555 XenStoreUnregisterWatch ((XENSTORE_WATCH *) Token); 1556 } 1557