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 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 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 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 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 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 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 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 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 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 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