XenStore.c 42 KB

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