1094a2239SPaul Durrant /*
2094a2239SPaul Durrant * Copyright (c) 2018 Citrix Systems Inc.
3094a2239SPaul Durrant *
4094a2239SPaul Durrant * This work is licensed under the terms of the GNU GPL, version 2 or later.
5094a2239SPaul Durrant * See the COPYING file in the top-level directory.
6094a2239SPaul Durrant */
7094a2239SPaul Durrant
8094a2239SPaul Durrant #include "qemu/osdep.h"
9094a2239SPaul Durrant #include "hw/xen/xen.h"
10094a2239SPaul Durrant #include "hw/xen/xen-bus.h"
11094a2239SPaul Durrant #include "hw/xen/xen-bus-helper.h"
12094a2239SPaul Durrant #include "qapi/error.h"
13ba2a92dbSPaul Durrant #include "trace.h"
14094a2239SPaul Durrant
15094a2239SPaul Durrant #include <glib/gprintf.h>
16094a2239SPaul Durrant
17094a2239SPaul Durrant struct xs_state {
18094a2239SPaul Durrant enum xenbus_state statenum;
19094a2239SPaul Durrant const char *statestr;
20094a2239SPaul Durrant };
21094a2239SPaul Durrant #define XS_STATE(state) { state, #state }
22094a2239SPaul Durrant
23094a2239SPaul Durrant static struct xs_state xs_state[] = {
24094a2239SPaul Durrant XS_STATE(XenbusStateUnknown),
25094a2239SPaul Durrant XS_STATE(XenbusStateInitialising),
26094a2239SPaul Durrant XS_STATE(XenbusStateInitWait),
27094a2239SPaul Durrant XS_STATE(XenbusStateInitialised),
28094a2239SPaul Durrant XS_STATE(XenbusStateConnected),
29094a2239SPaul Durrant XS_STATE(XenbusStateClosing),
30094a2239SPaul Durrant XS_STATE(XenbusStateClosed),
31094a2239SPaul Durrant XS_STATE(XenbusStateReconfiguring),
32094a2239SPaul Durrant XS_STATE(XenbusStateReconfigured),
33094a2239SPaul Durrant };
34094a2239SPaul Durrant
35094a2239SPaul Durrant #undef XS_STATE
36094a2239SPaul Durrant
xs_strstate(enum xenbus_state state)37094a2239SPaul Durrant const char *xs_strstate(enum xenbus_state state)
38094a2239SPaul Durrant {
39094a2239SPaul Durrant unsigned int i;
40094a2239SPaul Durrant
41094a2239SPaul Durrant for (i = 0; i < ARRAY_SIZE(xs_state); i++) {
42094a2239SPaul Durrant if (xs_state[i].statenum == state) {
43094a2239SPaul Durrant return xs_state[i].statestr;
44094a2239SPaul Durrant }
45094a2239SPaul Durrant }
46094a2239SPaul Durrant
47094a2239SPaul Durrant return "INVALID";
48094a2239SPaul Durrant }
49094a2239SPaul Durrant
xs_node_create(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,unsigned int owner,unsigned int domid,unsigned int perms,Error ** errp)50ba2a92dbSPaul Durrant void xs_node_create(struct qemu_xs_handle *h, xs_transaction_t tid,
51ba2a92dbSPaul Durrant const char *node, unsigned int owner, unsigned int domid,
52ba2a92dbSPaul Durrant unsigned int perms, Error **errp)
53094a2239SPaul Durrant {
54094a2239SPaul Durrant trace_xs_node_create(node);
55094a2239SPaul Durrant
56ba2a92dbSPaul Durrant if (!qemu_xen_xs_create(h, tid, owner, domid, perms, node)) {
57094a2239SPaul Durrant error_setg_errno(errp, errno, "failed to create node '%s'", node);
58094a2239SPaul Durrant }
59094a2239SPaul Durrant }
60094a2239SPaul Durrant
xs_node_destroy(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,Error ** errp)61ba2a92dbSPaul Durrant void xs_node_destroy(struct qemu_xs_handle *h, xs_transaction_t tid,
62094a2239SPaul Durrant const char *node, Error **errp)
63094a2239SPaul Durrant {
64094a2239SPaul Durrant trace_xs_node_destroy(node);
65094a2239SPaul Durrant
66ba2a92dbSPaul Durrant if (!qemu_xen_xs_destroy(h, tid, node)) {
67094a2239SPaul Durrant error_setg_errno(errp, errno, "failed to destroy node '%s'", node);
68094a2239SPaul Durrant }
69094a2239SPaul Durrant }
70094a2239SPaul Durrant
xs_node_vprintf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,va_list ap)71ba2a92dbSPaul Durrant void xs_node_vprintf(struct qemu_xs_handle *h, xs_transaction_t tid,
72094a2239SPaul Durrant const char *node, const char *key, Error **errp,
73094a2239SPaul Durrant const char *fmt, va_list ap)
74094a2239SPaul Durrant {
75094a2239SPaul Durrant char *path, *value;
76094a2239SPaul Durrant int len;
77094a2239SPaul Durrant
78094a2239SPaul Durrant path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
79094a2239SPaul Durrant g_strdup(key);
80094a2239SPaul Durrant len = g_vasprintf(&value, fmt, ap);
81094a2239SPaul Durrant
82094a2239SPaul Durrant trace_xs_node_vprintf(path, value);
83094a2239SPaul Durrant
84ba2a92dbSPaul Durrant if (!qemu_xen_xs_write(h, tid, path, value, len)) {
85094a2239SPaul Durrant error_setg_errno(errp, errno, "failed to write '%s' to '%s'",
86094a2239SPaul Durrant value, path);
87094a2239SPaul Durrant }
88094a2239SPaul Durrant
89094a2239SPaul Durrant g_free(value);
90094a2239SPaul Durrant g_free(path);
91094a2239SPaul Durrant }
92094a2239SPaul Durrant
xs_node_printf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,...)93ba2a92dbSPaul Durrant void xs_node_printf(struct qemu_xs_handle *h, xs_transaction_t tid,
94094a2239SPaul Durrant const char *node, const char *key, Error **errp,
95094a2239SPaul Durrant const char *fmt, ...)
96094a2239SPaul Durrant {
97094a2239SPaul Durrant va_list ap;
98094a2239SPaul Durrant
99094a2239SPaul Durrant va_start(ap, fmt);
100ba2a92dbSPaul Durrant xs_node_vprintf(h, tid, node, key, errp, fmt, ap);
101094a2239SPaul Durrant va_end(ap);
102094a2239SPaul Durrant }
103094a2239SPaul Durrant
xs_node_vscanf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,va_list ap)104ba2a92dbSPaul Durrant int xs_node_vscanf(struct qemu_xs_handle *h, xs_transaction_t tid,
105094a2239SPaul Durrant const char *node, const char *key, Error **errp,
106094a2239SPaul Durrant const char *fmt, va_list ap)
107094a2239SPaul Durrant {
108*76f26e46SDavid Woodhouse char *value;
109094a2239SPaul Durrant int rc;
110094a2239SPaul Durrant
111*76f26e46SDavid Woodhouse if (node && strlen(node) != 0) {
112*76f26e46SDavid Woodhouse value = xs_node_read(h, tid, NULL, errp, "%s/%s", node, key);
113*76f26e46SDavid Woodhouse } else {
114*76f26e46SDavid Woodhouse value = xs_node_read(h, tid, NULL, errp, "%s", key);
115*76f26e46SDavid Woodhouse }
116094a2239SPaul Durrant
117094a2239SPaul Durrant if (value) {
118094a2239SPaul Durrant rc = vsscanf(value, fmt, ap);
119094a2239SPaul Durrant } else {
120094a2239SPaul Durrant rc = EOF;
121094a2239SPaul Durrant }
122094a2239SPaul Durrant
123094a2239SPaul Durrant free(value);
124094a2239SPaul Durrant
125094a2239SPaul Durrant return rc;
126094a2239SPaul Durrant }
127094a2239SPaul Durrant
xs_node_scanf(struct qemu_xs_handle * h,xs_transaction_t tid,const char * node,const char * key,Error ** errp,const char * fmt,...)128ba2a92dbSPaul Durrant int xs_node_scanf(struct qemu_xs_handle *h, xs_transaction_t tid,
129094a2239SPaul Durrant const char *node, const char *key, Error **errp,
130094a2239SPaul Durrant const char *fmt, ...)
131094a2239SPaul Durrant {
132094a2239SPaul Durrant va_list ap;
133094a2239SPaul Durrant int rc;
134094a2239SPaul Durrant
135094a2239SPaul Durrant va_start(ap, fmt);
136ba2a92dbSPaul Durrant rc = xs_node_vscanf(h, tid, node, key, errp, fmt, ap);
137094a2239SPaul Durrant va_end(ap);
138094a2239SPaul Durrant
139094a2239SPaul Durrant return rc;
140094a2239SPaul Durrant }
14182a29e30SPaul Durrant
xs_node_read(struct qemu_xs_handle * h,xs_transaction_t tid,unsigned int * len,Error ** errp,const char * path_fmt,...)142e6cdeee9SDavid Woodhouse char *xs_node_read(struct qemu_xs_handle *h, xs_transaction_t tid,
143e6cdeee9SDavid Woodhouse unsigned int *len, Error **errp,
144e6cdeee9SDavid Woodhouse const char *path_fmt, ...)
145e6cdeee9SDavid Woodhouse {
146e6cdeee9SDavid Woodhouse char *path, *value;
147e6cdeee9SDavid Woodhouse va_list ap;
148e6cdeee9SDavid Woodhouse
149e6cdeee9SDavid Woodhouse va_start(ap, path_fmt);
150e6cdeee9SDavid Woodhouse path = g_strdup_vprintf(path_fmt, ap);
151e6cdeee9SDavid Woodhouse va_end(ap);
152e6cdeee9SDavid Woodhouse
153e6cdeee9SDavid Woodhouse value = qemu_xen_xs_read(h, tid, path, len);
154e6cdeee9SDavid Woodhouse trace_xs_node_read(path, value);
155e6cdeee9SDavid Woodhouse if (!value) {
156e6cdeee9SDavid Woodhouse error_setg_errno(errp, errno, "failed to read from '%s'", path);
157e6cdeee9SDavid Woodhouse }
158e6cdeee9SDavid Woodhouse
159e6cdeee9SDavid Woodhouse g_free(path);
160e6cdeee9SDavid Woodhouse
161e6cdeee9SDavid Woodhouse return value;
162e6cdeee9SDavid Woodhouse }
163e6cdeee9SDavid Woodhouse
xs_node_watch(struct qemu_xs_handle * h,const char * node,const char * key,xs_watch_fn fn,void * opaque,Error ** errp)164ba2a92dbSPaul Durrant struct qemu_xs_watch *xs_node_watch(struct qemu_xs_handle *h, const char *node,
165ba2a92dbSPaul Durrant const char *key, xs_watch_fn fn,
166ba2a92dbSPaul Durrant void *opaque, Error **errp)
16782a29e30SPaul Durrant {
16882a29e30SPaul Durrant char *path;
169ba2a92dbSPaul Durrant struct qemu_xs_watch *w;
17082a29e30SPaul Durrant
17182a29e30SPaul Durrant path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
17282a29e30SPaul Durrant g_strdup(key);
17382a29e30SPaul Durrant
17482a29e30SPaul Durrant trace_xs_node_watch(path);
17582a29e30SPaul Durrant
176ba2a92dbSPaul Durrant w = qemu_xen_xs_watch(h, path, fn, opaque);
177ba2a92dbSPaul Durrant if (!w) {
17882a29e30SPaul Durrant error_setg_errno(errp, errno, "failed to watch node '%s'", path);
17982a29e30SPaul Durrant }
18082a29e30SPaul Durrant
18182a29e30SPaul Durrant g_free(path);
182ba2a92dbSPaul Durrant
183ba2a92dbSPaul Durrant return w;
18482a29e30SPaul Durrant }
18582a29e30SPaul Durrant
xs_node_unwatch(struct qemu_xs_handle * h,struct qemu_xs_watch * w)186ba2a92dbSPaul Durrant void xs_node_unwatch(struct qemu_xs_handle *h, struct qemu_xs_watch *w)
18782a29e30SPaul Durrant {
188ba2a92dbSPaul Durrant qemu_xen_xs_unwatch(h, w);
18982a29e30SPaul Durrant }
190