You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdint.h>
  25. #include <stdarg.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <ipxe/io.h>
  30. #include <ipxe/nap.h>
  31. #include <ipxe/malloc.h>
  32. #include <ipxe/xen.h>
  33. #include <ipxe/xenevent.h>
  34. #include <ipxe/xenstore.h>
  35. /*
  36. * xs_wire.h attempts to define a static error table xsd_errors, which
  37. * interacts badly with the dynamically generated error numbers used
  38. * by iPXE. Prevent this table from being constructed by including
  39. * errno.h only after including xs_wire.h.
  40. *
  41. */
  42. #include <xen/io/xs_wire.h>
  43. #include <errno.h>
  44. /** @file
  45. *
  46. * XenStore interface
  47. *
  48. */
  49. /** Request identifier */
  50. static uint32_t xenstore_req_id;
  51. /**
  52. * Send XenStore request raw data
  53. *
  54. * @v xen Xen hypervisor
  55. * @v data Data buffer
  56. * @v len Length of data
  57. */
  58. static void xenstore_send ( struct xen_hypervisor *xen, const void *data,
  59. size_t len ) {
  60. struct xenstore_domain_interface *intf = xen->store.intf;
  61. XENSTORE_RING_IDX prod = readl ( &intf->req_prod );
  62. XENSTORE_RING_IDX cons;
  63. XENSTORE_RING_IDX idx;
  64. const char *bytes = data;
  65. size_t offset = 0;
  66. size_t fill;
  67. DBGCP ( intf, "XENSTORE raw request:\n" );
  68. DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( prod ), data, len );
  69. /* Write one byte at a time */
  70. while ( offset < len ) {
  71. /* Wait for space to become available */
  72. while ( 1 ) {
  73. cons = readl ( &intf->req_cons );
  74. fill = ( prod - cons );
  75. if ( fill < XENSTORE_RING_SIZE )
  76. break;
  77. DBGC2 ( xen, "." );
  78. cpu_nap();
  79. rmb();
  80. }
  81. /* Write byte */
  82. idx = MASK_XENSTORE_IDX ( prod++ );
  83. writeb ( bytes[offset++], &intf->req[idx] );
  84. }
  85. /* Update producer counter */
  86. wmb();
  87. writel ( prod, &intf->req_prod );
  88. wmb();
  89. }
  90. /**
  91. * Send XenStore request string (excluding terminating NUL)
  92. *
  93. * @v xen Xen hypervisor
  94. * @v string String
  95. */
  96. static void xenstore_send_string ( struct xen_hypervisor *xen,
  97. const char *string ) {
  98. xenstore_send ( xen, string, strlen ( string ) );
  99. }
  100. /**
  101. * Receive XenStore response raw data
  102. *
  103. * @v xen Xen hypervisor
  104. * @v data Data buffer, or NULL to discard data
  105. * @v len Length of data
  106. */
  107. static void xenstore_recv ( struct xen_hypervisor *xen, void *data,
  108. size_t len ) {
  109. struct xenstore_domain_interface *intf = xen->store.intf;
  110. XENSTORE_RING_IDX cons = readl ( &intf->rsp_cons );
  111. XENSTORE_RING_IDX prod;
  112. XENSTORE_RING_IDX idx;
  113. char *bytes = data;
  114. size_t offset = 0;
  115. size_t fill;
  116. DBGCP ( intf, "XENSTORE raw response:\n" );
  117. /* Read one byte at a time */
  118. while ( offset < len ) {
  119. /* Wait for data to be ready */
  120. while ( 1 ) {
  121. prod = readl ( &intf->rsp_prod );
  122. fill = ( prod - cons );
  123. if ( fill > 0 )
  124. break;
  125. DBGC2 ( xen, "." );
  126. cpu_nap();
  127. rmb();
  128. }
  129. /* Read byte */
  130. idx = MASK_XENSTORE_IDX ( cons++ );
  131. if ( data )
  132. bytes[offset++] = readb ( &intf->rsp[idx] );
  133. }
  134. if ( data )
  135. DBGCP_HDA ( intf, MASK_XENSTORE_IDX ( cons - len ), data, len );
  136. /* Update consumer counter */
  137. writel ( cons, &intf->rsp_cons );
  138. wmb();
  139. }
  140. /**
  141. * Send XenStore request
  142. *
  143. * @v xen Xen hypervisor
  144. * @v type Message type
  145. * @v req_id Request ID
  146. * @v value Value, or NULL to omit
  147. * @v key Key path components
  148. * @ret rc Return status code
  149. */
  150. static int xenstore_request ( struct xen_hypervisor *xen,
  151. enum xsd_sockmsg_type type, uint32_t req_id,
  152. const char *value, va_list key ) {
  153. struct xsd_sockmsg msg;
  154. struct evtchn_send event;
  155. const char *string;
  156. va_list tmp;
  157. int xenrc;
  158. int rc;
  159. /* Construct message header */
  160. msg.type = type;
  161. msg.req_id = req_id;
  162. msg.tx_id = 0;
  163. msg.len = 0;
  164. DBGC2 ( xen, "XENSTORE request ID %d type %d ", req_id, type );
  165. /* Calculate total length */
  166. va_copy ( tmp, key );
  167. while ( ( string = va_arg ( tmp, const char * ) ) != NULL ) {
  168. DBGC2 ( xen, "%s%s", ( msg.len ? "/" : "" ), string );
  169. msg.len += ( strlen ( string ) + 1 /* '/' or NUL */ );
  170. }
  171. va_end ( tmp );
  172. if ( value ) {
  173. DBGC2 ( xen, " = \"%s\"", value );
  174. msg.len += strlen ( value );
  175. }
  176. DBGC2 ( xen, "\n" );
  177. /* Send message */
  178. xenstore_send ( xen, &msg, sizeof ( msg ) );
  179. string = va_arg ( key, const char * );
  180. assert ( string != NULL );
  181. xenstore_send_string ( xen, string );
  182. while ( ( string = va_arg ( key, const char * ) ) != NULL ) {
  183. xenstore_send_string ( xen, "/" );
  184. xenstore_send_string ( xen, string );
  185. }
  186. xenstore_send ( xen, "", 1 ); /* Separating NUL */
  187. if ( value )
  188. xenstore_send_string ( xen, value );
  189. /* Notify the back end */
  190. event.port = xen->store.port;
  191. if ( ( xenrc = xenevent_send ( xen, &event ) ) != 0 ) {
  192. rc = -EXEN ( xenrc );
  193. DBGC ( xen, "XENSTORE could not notify back end: %s\n",
  194. strerror ( rc ) );
  195. return rc;
  196. }
  197. return 0;
  198. }
  199. /**
  200. * Receive XenStore response
  201. *
  202. * @v xen Xen hypervisor
  203. * @v req_id Request ID
  204. * @v value Value to fill in
  205. * @v len Length to fill in
  206. * @ret rc Return status code
  207. *
  208. * The caller is responsible for eventually calling free() on the
  209. * returned value. Note that the value may comprise multiple
  210. * NUL-terminated strings concatenated together. A terminating NUL
  211. * will always be appended to the returned value.
  212. */
  213. static int xenstore_response ( struct xen_hypervisor *xen, uint32_t req_id,
  214. char **value, size_t *len ) {
  215. struct xsd_sockmsg msg;
  216. char *string;
  217. int rc;
  218. /* Wait for response to become available */
  219. while ( ! xenevent_pending ( xen, xen->store.port ) )
  220. cpu_nap();
  221. /* Receive message header */
  222. xenstore_recv ( xen, &msg, sizeof ( msg ) );
  223. *len = msg.len;
  224. /* Allocate space for response */
  225. *value = zalloc ( msg.len + 1 /* terminating NUL */ );
  226. /* Receive data. Do this even if allocation failed, or if the
  227. * request ID was incorrect, to avoid leaving data in the
  228. * ring.
  229. */
  230. xenstore_recv ( xen, *value, msg.len );
  231. /* Validate request ID */
  232. if ( msg.req_id != req_id ) {
  233. DBGC ( xen, "XENSTORE response ID mismatch (got %d, expected "
  234. "%d)\n", msg.req_id, req_id );
  235. rc = -EPROTO;
  236. goto err_req_id;
  237. }
  238. /* Check for allocation failure */
  239. if ( ! *value ) {
  240. DBGC ( xen, "XENSTORE could not allocate %d bytes for "
  241. "response\n", msg.len );
  242. rc = -ENOMEM;
  243. goto err_alloc;
  244. }
  245. /* Check for explicit errors */
  246. if ( msg.type == XS_ERROR ) {
  247. DBGC ( xen, "XENSTORE response error \"%s\"\n", *value );
  248. rc = -EIO;
  249. goto err_explicit;
  250. }
  251. DBGC2 ( xen, "XENSTORE response ID %d\n", req_id );
  252. if ( DBG_EXTRA ) {
  253. for ( string = *value ; string < ( *value + msg.len ) ;
  254. string += ( strlen ( string ) + 1 /* NUL */ ) ) {
  255. DBGC2 ( xen, " - \"%s\"\n", string );
  256. }
  257. }
  258. return 0;
  259. err_explicit:
  260. err_alloc:
  261. err_req_id:
  262. free ( *value );
  263. *value = NULL;
  264. return rc;
  265. }
  266. /**
  267. * Issue a XenStore message
  268. *
  269. * @v xen Xen hypervisor
  270. * @v type Message type
  271. * @v response Response value to fill in, or NULL to discard
  272. * @v len Response length to fill in, or NULL to ignore
  273. * @v request Request value, or NULL to omit
  274. * @v key Key path components
  275. * @ret rc Return status code
  276. */
  277. static int xenstore_message ( struct xen_hypervisor *xen,
  278. enum xsd_sockmsg_type type, char **response,
  279. size_t *len, const char *request, va_list key ) {
  280. char *response_value;
  281. size_t response_len;
  282. int rc;
  283. /* Send request */
  284. if ( ( rc = xenstore_request ( xen, type, ++xenstore_req_id,
  285. request, key ) ) != 0 )
  286. return rc;
  287. /* Receive response */
  288. if ( ( rc = xenstore_response ( xen, xenstore_req_id, &response_value,
  289. &response_len ) ) != 0 )
  290. return rc;
  291. /* Return response, if applicable */
  292. if ( response ) {
  293. *response = response_value;
  294. } else {
  295. free ( response_value );
  296. }
  297. if ( len )
  298. *len = response_len;
  299. return 0;
  300. }
  301. /**
  302. * Read XenStore value
  303. *
  304. * @v xen Xen hypervisor
  305. * @v value Value to fill in
  306. * @v key Key path components
  307. * @ret rc Return status code
  308. *
  309. * On a successful return, the caller is responsible for calling
  310. * free() on the returned value.
  311. */
  312. static int xenstore_vread ( struct xen_hypervisor *xen, char **value,
  313. va_list key ) {
  314. return xenstore_message ( xen, XS_READ, value, NULL, NULL, key );
  315. }
  316. /**
  317. * Read XenStore value
  318. *
  319. * @v xen Xen hypervisor
  320. * @v value Value to fill in
  321. * @v ... Key path components
  322. * @ret rc Return status code
  323. *
  324. * On a successful return, the caller is responsible for calling
  325. * free() on the returned value.
  326. */
  327. __attribute__ (( sentinel )) int
  328. xenstore_read ( struct xen_hypervisor *xen, char **value, ... ) {
  329. va_list key;
  330. int rc;
  331. va_start ( key, value );
  332. rc = xenstore_vread ( xen, value, key );
  333. va_end ( key );
  334. return rc;
  335. }
  336. /**
  337. * Read XenStore numeric value
  338. *
  339. * @v xen Xen hypervisor
  340. * @v num Numeric value to fill in
  341. * @v ... Key path components
  342. * @ret rc Return status code
  343. */
  344. __attribute__ (( sentinel )) int
  345. xenstore_read_num ( struct xen_hypervisor *xen, unsigned long *num, ... ) {
  346. va_list key;
  347. char *value;
  348. char *endp;
  349. int rc;
  350. /* Try to read text value */
  351. va_start ( key, num );
  352. rc = xenstore_vread ( xen, &value, key );
  353. va_end ( key );
  354. if ( rc != 0 )
  355. goto err_read;
  356. /* Try to parse as numeric value */
  357. *num = strtoul ( value, &endp, 10 );
  358. if ( ( *value == '\0' ) || ( *endp != '\0' ) ) {
  359. DBGC ( xen, "XENSTORE found invalid numeric value \"%s\"\n",
  360. value );
  361. rc = -EINVAL;
  362. goto err_strtoul;
  363. }
  364. err_strtoul:
  365. free ( value );
  366. err_read:
  367. return rc;
  368. }
  369. /**
  370. * Write XenStore value
  371. *
  372. * @v xen Xen hypervisor
  373. * @v value Value
  374. * @v key Key path components
  375. * @ret rc Return status code
  376. */
  377. static int xenstore_vwrite ( struct xen_hypervisor *xen, const char *value,
  378. va_list key ) {
  379. return xenstore_message ( xen, XS_WRITE, NULL, NULL, value, key );
  380. }
  381. /**
  382. * Write XenStore value
  383. *
  384. * @v xen Xen hypervisor
  385. * @v value Value
  386. * @v ... Key path components
  387. * @ret rc Return status code
  388. */
  389. __attribute__ (( sentinel )) int
  390. xenstore_write ( struct xen_hypervisor *xen, const char *value, ... ) {
  391. va_list key;
  392. int rc;
  393. va_start ( key, value );
  394. rc = xenstore_vwrite ( xen, value, key );
  395. va_end ( key );
  396. return rc;
  397. }
  398. /**
  399. * Write XenStore numeric value
  400. *
  401. * @v xen Xen hypervisor
  402. * @v num Numeric value
  403. * @v ... Key path components
  404. * @ret rc Return status code
  405. */
  406. __attribute__ (( sentinel )) int
  407. xenstore_write_num ( struct xen_hypervisor *xen, unsigned long num, ... ) {
  408. char value[ 21 /* "18446744073709551615" + NUL */ ];
  409. va_list key;
  410. int rc;
  411. /* Construct value */
  412. snprintf ( value, sizeof ( value ), "%ld", num );
  413. /* Write value */
  414. va_start ( key, num );
  415. rc = xenstore_vwrite ( xen, value, key );
  416. va_end ( key );
  417. return rc;
  418. }
  419. /**
  420. * Delete XenStore value
  421. *
  422. * @v xen Xen hypervisor
  423. * @v ... Key path components
  424. * @ret rc Return status code
  425. */
  426. __attribute__ (( sentinel )) int
  427. xenstore_rm ( struct xen_hypervisor *xen, ... ) {
  428. va_list key;
  429. int rc;
  430. va_start ( key, xen );
  431. rc = xenstore_message ( xen, XS_RM, NULL, NULL, NULL, key );
  432. va_end ( key );
  433. return rc;
  434. }
  435. /**
  436. * Read XenStore directory
  437. *
  438. * @v xen Xen hypervisor
  439. * @v children Child key names to fill in
  440. * @v len Length of child key names to fill in
  441. * @v ... Key path components
  442. * @ret rc Return status code
  443. */
  444. __attribute__ (( sentinel )) int
  445. xenstore_directory ( struct xen_hypervisor *xen, char **children, size_t *len,
  446. ... ) {
  447. va_list key;
  448. int rc;
  449. va_start ( key, len );
  450. rc = xenstore_message ( xen, XS_DIRECTORY, children, len, NULL, key );
  451. va_end ( key );
  452. return rc;
  453. }
  454. /**
  455. * Dump XenStore directory contents (for debugging)
  456. *
  457. * @v xen Xen hypervisor
  458. * @v key Key
  459. */
  460. void xenstore_dump ( struct xen_hypervisor *xen, const char *key ) {
  461. char *value;
  462. char *children;
  463. char *child;
  464. char *child_key;
  465. size_t len;
  466. int rc;
  467. /* Try to dump current key as a value */
  468. if ( ( rc = xenstore_read ( xen, &value, key, NULL ) ) == 0 ) {
  469. DBGC ( xen, "%s = \"%s\"\n", key, value );
  470. free ( value );
  471. }
  472. /* Try to recurse into each child in turn */
  473. if ( ( rc = xenstore_directory ( xen, &children, &len, key,
  474. NULL ) ) == 0 ) {
  475. for ( child = children ; child < ( children + len ) ;
  476. child += ( strlen ( child ) + 1 /* NUL */ ) ) {
  477. /* Construct child key */
  478. if ( asprintf ( &child_key, "%s/%s", key, child ) < 0 ){
  479. DBGC ( xen, "XENSTORE could not allocate child "
  480. "key \"%s/%s\"\n", key, child );
  481. rc = -ENOMEM;
  482. break;
  483. }
  484. /* Recurse into child key, continuing on error */
  485. xenstore_dump ( xen, child_key );
  486. free ( child_key );
  487. }
  488. free ( children );
  489. }
  490. }