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