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" 13*ba2a92dbSPaul 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 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 50*ba2a92dbSPaul Durrant void xs_node_create(struct qemu_xs_handle *h, xs_transaction_t tid, 51*ba2a92dbSPaul Durrant const char *node, unsigned int owner, unsigned int domid, 52*ba2a92dbSPaul Durrant unsigned int perms, Error **errp) 53094a2239SPaul Durrant { 54094a2239SPaul Durrant trace_xs_node_create(node); 55094a2239SPaul Durrant 56*ba2a92dbSPaul 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 61*ba2a92dbSPaul 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 66*ba2a92dbSPaul 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 71*ba2a92dbSPaul 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 84*ba2a92dbSPaul 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 93*ba2a92dbSPaul 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); 100*ba2a92dbSPaul Durrant xs_node_vprintf(h, tid, node, key, errp, fmt, ap); 101094a2239SPaul Durrant va_end(ap); 102094a2239SPaul Durrant } 103094a2239SPaul Durrant 104*ba2a92dbSPaul 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 { 108094a2239SPaul Durrant char *path, *value; 109094a2239SPaul Durrant int rc; 110094a2239SPaul Durrant 111094a2239SPaul Durrant path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 112094a2239SPaul Durrant g_strdup(key); 113*ba2a92dbSPaul Durrant value = qemu_xen_xs_read(h, tid, path, NULL); 114094a2239SPaul Durrant 115094a2239SPaul Durrant trace_xs_node_vscanf(path, value); 116094a2239SPaul Durrant 117094a2239SPaul Durrant if (value) { 118094a2239SPaul Durrant rc = vsscanf(value, fmt, ap); 119094a2239SPaul Durrant } else { 120094a2239SPaul Durrant error_setg_errno(errp, errno, "failed to read from '%s'", 121094a2239SPaul Durrant path); 122094a2239SPaul Durrant rc = EOF; 123094a2239SPaul Durrant } 124094a2239SPaul Durrant 125094a2239SPaul Durrant free(value); 126094a2239SPaul Durrant g_free(path); 127094a2239SPaul Durrant 128094a2239SPaul Durrant return rc; 129094a2239SPaul Durrant } 130094a2239SPaul Durrant 131*ba2a92dbSPaul Durrant int xs_node_scanf(struct qemu_xs_handle *h, xs_transaction_t tid, 132094a2239SPaul Durrant const char *node, const char *key, Error **errp, 133094a2239SPaul Durrant const char *fmt, ...) 134094a2239SPaul Durrant { 135094a2239SPaul Durrant va_list ap; 136094a2239SPaul Durrant int rc; 137094a2239SPaul Durrant 138094a2239SPaul Durrant va_start(ap, fmt); 139*ba2a92dbSPaul Durrant rc = xs_node_vscanf(h, tid, node, key, errp, fmt, ap); 140094a2239SPaul Durrant va_end(ap); 141094a2239SPaul Durrant 142094a2239SPaul Durrant return rc; 143094a2239SPaul Durrant } 14482a29e30SPaul Durrant 145*ba2a92dbSPaul Durrant struct qemu_xs_watch *xs_node_watch(struct qemu_xs_handle *h, const char *node, 146*ba2a92dbSPaul Durrant const char *key, xs_watch_fn fn, 147*ba2a92dbSPaul Durrant void *opaque, Error **errp) 14882a29e30SPaul Durrant { 14982a29e30SPaul Durrant char *path; 150*ba2a92dbSPaul Durrant struct qemu_xs_watch *w; 15182a29e30SPaul Durrant 15282a29e30SPaul Durrant path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) : 15382a29e30SPaul Durrant g_strdup(key); 15482a29e30SPaul Durrant 15582a29e30SPaul Durrant trace_xs_node_watch(path); 15682a29e30SPaul Durrant 157*ba2a92dbSPaul Durrant w = qemu_xen_xs_watch(h, path, fn, opaque); 158*ba2a92dbSPaul Durrant if (!w) { 15982a29e30SPaul Durrant error_setg_errno(errp, errno, "failed to watch node '%s'", path); 16082a29e30SPaul Durrant } 16182a29e30SPaul Durrant 16282a29e30SPaul Durrant g_free(path); 163*ba2a92dbSPaul Durrant 164*ba2a92dbSPaul Durrant return w; 16582a29e30SPaul Durrant } 16682a29e30SPaul Durrant 167*ba2a92dbSPaul Durrant void xs_node_unwatch(struct qemu_xs_handle *h, struct qemu_xs_watch *w) 16882a29e30SPaul Durrant { 169*ba2a92dbSPaul Durrant qemu_xen_xs_unwatch(h, w); 17082a29e30SPaul Durrant } 171