blob: b2b2cc9c5d5e1a403ebcdf18c41959da615da6c2 [file] [log] [blame]
Paul Durrant094a2232019-01-08 14:48:49 +00001/*
2 * Copyright (c) 2018 Citrix Systems Inc.
3 *
4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
5 * See the COPYING file in the top-level directory.
6 */
7
8#include "qemu/osdep.h"
Paul Durrant094a2232019-01-08 14:48:49 +00009#include "hw/xen/xen.h"
10#include "hw/xen/xen-bus.h"
11#include "hw/xen/xen-bus-helper.h"
12#include "qapi/error.h"
Paul Durrantba2a92d2023-01-02 11:05:16 +000013#include "trace.h"
Paul Durrant094a2232019-01-08 14:48:49 +000014
15#include <glib/gprintf.h>
16
17struct xs_state {
18 enum xenbus_state statenum;
19 const char *statestr;
20};
21#define XS_STATE(state) { state, #state }
22
23static struct xs_state xs_state[] = {
24 XS_STATE(XenbusStateUnknown),
25 XS_STATE(XenbusStateInitialising),
26 XS_STATE(XenbusStateInitWait),
27 XS_STATE(XenbusStateInitialised),
28 XS_STATE(XenbusStateConnected),
29 XS_STATE(XenbusStateClosing),
30 XS_STATE(XenbusStateClosed),
31 XS_STATE(XenbusStateReconfiguring),
32 XS_STATE(XenbusStateReconfigured),
33};
34
35#undef XS_STATE
36
37const char *xs_strstate(enum xenbus_state state)
38{
39 unsigned int i;
40
41 for (i = 0; i < ARRAY_SIZE(xs_state); i++) {
42 if (xs_state[i].statenum == state) {
43 return xs_state[i].statestr;
44 }
45 }
46
47 return "INVALID";
48}
49
Paul Durrantba2a92d2023-01-02 11:05:16 +000050void xs_node_create(struct qemu_xs_handle *h, xs_transaction_t tid,
51 const char *node, unsigned int owner, unsigned int domid,
52 unsigned int perms, Error **errp)
Paul Durrant094a2232019-01-08 14:48:49 +000053{
54 trace_xs_node_create(node);
55
Paul Durrantba2a92d2023-01-02 11:05:16 +000056 if (!qemu_xen_xs_create(h, tid, owner, domid, perms, node)) {
Paul Durrant094a2232019-01-08 14:48:49 +000057 error_setg_errno(errp, errno, "failed to create node '%s'", node);
Paul Durrant094a2232019-01-08 14:48:49 +000058 }
59}
60
Paul Durrantba2a92d2023-01-02 11:05:16 +000061void xs_node_destroy(struct qemu_xs_handle *h, xs_transaction_t tid,
Paul Durrant094a2232019-01-08 14:48:49 +000062 const char *node, Error **errp)
63{
64 trace_xs_node_destroy(node);
65
Paul Durrantba2a92d2023-01-02 11:05:16 +000066 if (!qemu_xen_xs_destroy(h, tid, node)) {
Paul Durrant094a2232019-01-08 14:48:49 +000067 error_setg_errno(errp, errno, "failed to destroy node '%s'", node);
68 }
69}
70
Paul Durrantba2a92d2023-01-02 11:05:16 +000071void xs_node_vprintf(struct qemu_xs_handle *h, xs_transaction_t tid,
Paul Durrant094a2232019-01-08 14:48:49 +000072 const char *node, const char *key, Error **errp,
73 const char *fmt, va_list ap)
74{
75 char *path, *value;
76 int len;
77
78 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
79 g_strdup(key);
80 len = g_vasprintf(&value, fmt, ap);
81
82 trace_xs_node_vprintf(path, value);
83
Paul Durrantba2a92d2023-01-02 11:05:16 +000084 if (!qemu_xen_xs_write(h, tid, path, value, len)) {
Paul Durrant094a2232019-01-08 14:48:49 +000085 error_setg_errno(errp, errno, "failed to write '%s' to '%s'",
86 value, path);
87 }
88
89 g_free(value);
90 g_free(path);
91}
92
Paul Durrantba2a92d2023-01-02 11:05:16 +000093void xs_node_printf(struct qemu_xs_handle *h, xs_transaction_t tid,
Paul Durrant094a2232019-01-08 14:48:49 +000094 const char *node, const char *key, Error **errp,
95 const char *fmt, ...)
96{
97 va_list ap;
98
99 va_start(ap, fmt);
Paul Durrantba2a92d2023-01-02 11:05:16 +0000100 xs_node_vprintf(h, tid, node, key, errp, fmt, ap);
Paul Durrant094a2232019-01-08 14:48:49 +0000101 va_end(ap);
102}
103
Paul Durrantba2a92d2023-01-02 11:05:16 +0000104int xs_node_vscanf(struct qemu_xs_handle *h, xs_transaction_t tid,
Paul Durrant094a2232019-01-08 14:48:49 +0000105 const char *node, const char *key, Error **errp,
106 const char *fmt, va_list ap)
107{
108 char *path, *value;
109 int rc;
110
111 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
112 g_strdup(key);
Paul Durrantba2a92d2023-01-02 11:05:16 +0000113 value = qemu_xen_xs_read(h, tid, path, NULL);
Paul Durrant094a2232019-01-08 14:48:49 +0000114
115 trace_xs_node_vscanf(path, value);
116
117 if (value) {
118 rc = vsscanf(value, fmt, ap);
119 } else {
120 error_setg_errno(errp, errno, "failed to read from '%s'",
121 path);
122 rc = EOF;
123 }
124
125 free(value);
126 g_free(path);
127
128 return rc;
129}
130
Paul Durrantba2a92d2023-01-02 11:05:16 +0000131int xs_node_scanf(struct qemu_xs_handle *h, xs_transaction_t tid,
Paul Durrant094a2232019-01-08 14:48:49 +0000132 const char *node, const char *key, Error **errp,
133 const char *fmt, ...)
134{
135 va_list ap;
136 int rc;
137
138 va_start(ap, fmt);
Paul Durrantba2a92d2023-01-02 11:05:16 +0000139 rc = xs_node_vscanf(h, tid, node, key, errp, fmt, ap);
Paul Durrant094a2232019-01-08 14:48:49 +0000140 va_end(ap);
141
142 return rc;
143}
Paul Durrant82a29e32019-01-08 14:48:50 +0000144
Paul Durrantba2a92d2023-01-02 11:05:16 +0000145struct qemu_xs_watch *xs_node_watch(struct qemu_xs_handle *h, const char *node,
146 const char *key, xs_watch_fn fn,
147 void *opaque, Error **errp)
Paul Durrant82a29e32019-01-08 14:48:50 +0000148{
149 char *path;
Paul Durrantba2a92d2023-01-02 11:05:16 +0000150 struct qemu_xs_watch *w;
Paul Durrant82a29e32019-01-08 14:48:50 +0000151
152 path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
153 g_strdup(key);
154
155 trace_xs_node_watch(path);
156
Paul Durrantba2a92d2023-01-02 11:05:16 +0000157 w = qemu_xen_xs_watch(h, path, fn, opaque);
158 if (!w) {
Paul Durrant82a29e32019-01-08 14:48:50 +0000159 error_setg_errno(errp, errno, "failed to watch node '%s'", path);
160 }
161
162 g_free(path);
Paul Durrantba2a92d2023-01-02 11:05:16 +0000163
164 return w;
Paul Durrant82a29e32019-01-08 14:48:50 +0000165}
166
Paul Durrantba2a92d2023-01-02 11:05:16 +0000167void xs_node_unwatch(struct qemu_xs_handle *h, struct qemu_xs_watch *w)
Paul Durrant82a29e32019-01-08 14:48:50 +0000168{
Paul Durrantba2a92d2023-01-02 11:05:16 +0000169 qemu_xen_xs_unwatch(h, w);
Paul Durrant82a29e32019-01-08 14:48:50 +0000170}