On 7/1/20 6:29 PM, Anastasiia Lukianenko wrote:
> From: Oleksandr Andrushchenko <oleksandr_andrushche...@epam.com>
>
> Make required updates to run on u-boot and strip test code.
>
> Signed-off-by: Anastasiia Lukianenko <anastasiia_lukiane...@epam.com>
> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushche...@epam.com>
> ---
>  arch/arm/Kconfig                          |   1 +
>  board/xen/xenguest_arm64/xenguest_arm64.c |  16 +-
>  drivers/xen/Makefile                      |   1 +
>  drivers/xen/hypervisor.c                  |   2 +
>  drivers/xen/xenbus.c                      | 547 ++++++++++++++++++++++
>  include/xen/xenbus.h                      |  86 ++++
>  6 files changed, 652 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/xen/xenbus.c
>  create mode 100644 include/xen/xenbus.h
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index d4de1139aa..bcd9ab5c9d 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1724,6 +1724,7 @@ config TARGET_XENGUEST_ARM64
>       select OF_CONTROL
>       select LINUX_KERNEL_IMAGE_HEADER
>       select XEN_SERIAL
> +     select SSCANF
>  endchoice
>
>  config ARCH_SUPPORT_TFABOOT
> diff --git a/board/xen/xenguest_arm64/xenguest_arm64.c 
> b/board/xen/xenguest_arm64/xenguest_arm64.c
> index fd10a002e9..e8621f7174 100644
> --- a/board/xen/xenguest_arm64/xenguest_arm64.c
> +++ b/board/xen/xenguest_arm64/xenguest_arm64.c
> @@ -67,7 +67,7 @@ static int setup_mem_map(void)
>
>       /*
>        * Add "magic" region which is used by Xen to provide some essentials
> -      * for the guest: we need console.
> +      * for the guest: we need console and xenstore.
>        */
>       ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_CONSOLE_PFN, &gfn);
>       if (ret < 0) {
> @@ -83,6 +83,20 @@ static int setup_mem_map(void)
>                               PTE_BLOCK_INNER_SHARE);
>       i++;
>
> +     ret = hvm_get_parameter_maintain_dcache(HVM_PARAM_STORE_PFN, &gfn);
> +     if (ret < 0) {
> +             printf("%s: Can't get HVM_PARAM_STORE_PFN, ret %d\n",
> +                    __func__, ret);
> +             return -EINVAL;
> +     }
> +
> +     xen_mem_map[i].virt = PFN_PHYS(gfn);
> +     xen_mem_map[i].phys = PFN_PHYS(gfn);
> +     xen_mem_map[i].size = PAGE_SIZE;
> +     xen_mem_map[i].attrs = (PTE_BLOCK_MEMTYPE(MT_NORMAL) |
> +                             PTE_BLOCK_INNER_SHARE);
> +     i++;
> +
>       mem = get_next_memory_node(blob, -1);
>       if (mem < 0) {
>               printf("%s: Missing /memory node\n", __func__);
> diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
> index 0ad35edefb..9d0f604aaa 100644
> --- a/drivers/xen/Makefile
> +++ b/drivers/xen/Makefile
> @@ -4,3 +4,4 @@
>
>  obj-y += hypervisor.o
>  obj-y += events.o
> +obj-y += xenbus.o
> diff --git a/drivers/xen/hypervisor.c b/drivers/xen/hypervisor.c
> index 975e552242..d7fbacb08e 100644
> --- a/drivers/xen/hypervisor.c
> +++ b/drivers/xen/hypervisor.c
> @@ -38,6 +38,7 @@
>
>  #include <xen/hvm.h>
>  #include <xen/events.h>
> +#include <xen/xenbus.h>
>  #include <xen/interface/memory.h>
>
>  #define active_evtchns(cpu, sh, idx) \
> @@ -273,5 +274,6 @@ void xen_init(void)
>
>       map_shared_info(NULL);
>       init_events();
> +     init_xenbus();
>  }
>
> diff --git a/drivers/xen/xenbus.c b/drivers/xen/xenbus.c
> new file mode 100644
> index 0000000000..64eb28e843
> --- /dev/null
> +++ b/drivers/xen/xenbus.c
> @@ -0,0 +1,547 @@
> +/*

Add an SPDX header, please.

> + ****************************************************************************
> + * (C) 2006 - Cambridge University
> + * (C) 2020 - EPAM Systems Inc.
> + ****************************************************************************
> + *
> + *           File: xenbus.c
> + *     Author: Steven Smith (so...@cam.ac.uk)
> + *    Changes: Grzegorz Milos (gm...@cam.ac.uk)
> + *    Changes: John D. Ramsdell
> + *
> + *           Date: Jun 2006, chages Aug 2005

%s/chages/changes/ ?
Does time run in reverse in Cambridge?

> + *
> + * Environment: Xen Minimal OS

This is U-Boot.

Better provide a link to the original source.

> + * Description: Minimal implementation of xenbus
> + *
> + ****************************************************************************

Can we get rid of this not U-Boot style formatting?

> + **/
> +
> +#include <common.h>
> +#include <log.h>
> +
> +#include <asm/armv8/mmu.h>
> +#include <asm/io.h>
> +#include <asm/xen/system.h>
> +
> +#include <linux/bug.h>
> +#include <linux/compat.h>
> +
> +#include <xen/events.h>
> +#include <xen/hvm.h>
> +#include <xen/xenbus.h>
> +
> +#include <xen/interface/io/xs_wire.h>
> +
> +#define map_frame_virt(v)    (v << PAGE_SHIFT)
> +
> +#define SCNd16                       "d"
> +
> +/* Wait for reply time out, ms */
> +#define WAIT_XENBUS_TO_MS    5000
> +/* Polling time out, ms */
> +#define WAIT_XENBUS_POLL_TO_MS       1
> +
> +static struct xenstore_domain_interface *xenstore_buf;
> +
> +static char *errmsg(struct xsd_sockmsg *rep);
> +
> +u32 xenbus_evtchn;
> +
> +struct write_req {
> +     const void *data;
> +     unsigned int len;
> +};
> +
> +static void memcpy_from_ring(const void *r, void *d, int off, int len)
> +{
> +     int c1, c2;
> +     const char *ring = r;
> +     char *dest = d;
> +
> +     c1 = min(len, XENSTORE_RING_SIZE - off);
> +     c2 = len - c1;
> +     memcpy(dest, ring + off, c1);
> +     memcpy(dest + c1, ring, c2);
> +}
> +
> +static bool xenbus_get_reply(struct xsd_sockmsg **req_reply)
> +{
> +     struct xsd_sockmsg msg;
> +     unsigned int prod = xenstore_buf->rsp_prod;
> +
> +again:
> +     if (!wait_event_timeout(NULL, prod != xenstore_buf->rsp_prod,
> +                             WAIT_XENBUS_TO_MS)) {
> +             printk("%s: wait_event timeout\n", __func__);
> +             return false;
> +     }
> +
> +     prod = xenstore_buf->rsp_prod;
> +     if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
> +             goto again;
> +
> +     rmb();
> +     memcpy_from_ring(xenstore_buf->rsp, &msg,
> +                      MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
> +                      sizeof(msg));
> +
> +     if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg) + 
> msg.len)
> +             goto again;
> +
> +     /* We do not support and expect any Xen bus wathes. */
> +     BUG_ON(msg.type == XS_WATCH_EVENT);
> +
> +     *req_reply = malloc(sizeof(msg) + msg.len);
> +     memcpy_from_ring(xenstore_buf->rsp, *req_reply,
> +                      MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
> +                      msg.len + sizeof(msg));
> +     mb();
> +     xenstore_buf->rsp_cons += msg.len + sizeof(msg);
> +
> +     wmb();
> +     notify_remote_via_evtchn(xenbus_evtchn);
> +     return true;
> +}
> +

Document functions, please.

https://www.kernel.org/doc/html/latest/doc-guide/kernel-doc.html#function-documentation

Best regards

Heinrich

> +char *xenbus_switch_state(xenbus_transaction_t xbt, const char *path,
> +                       XenbusState state)
> +{
> +     char *current_state;
> +     char *msg = NULL;
> +     char *msg2 = NULL;
> +     char value[2];
> +     XenbusState rs;
> +     int xbt_flag = 0;
> +     int retry = 0;
> +
> +     do {
> +             if (xbt == XBT_NIL) {
> +                     msg = xenbus_transaction_start(&xbt);
> +                     if (msg)
> +                             goto exit;
> +                     xbt_flag = 1;
> +             }
> +
> +             msg = xenbus_read(xbt, path, &current_state);
> +             if (msg)
> +                     goto exit;
> +
> +             rs = (XenbusState)(current_state[0] - '0');
> +             free(current_state);
> +             if (rs == state) {
> +                     msg = NULL;
> +                     goto exit;
> +             }
> +
> +             snprintf(value, 2, "%d", state);
> +             msg = xenbus_write(xbt, path, value);
> +
> +exit:
> +             if (xbt_flag) {
> +                     msg2 = xenbus_transaction_end(xbt, 0, &retry);
> +                     xbt = XBT_NIL;
> +             }
> +             if (msg == NULL && msg2 != NULL)
> +                     msg = msg2;
> +             else
> +                     free(msg2);
> +     } while (retry);
> +
> +     return msg;
> +}
> +
> +char *xenbus_wait_for_state_change(const char *path, XenbusState *state)
> +{
> +     for (;;) {
> +             char *res, *msg;
> +             XenbusState rs;
> +
> +             msg = xenbus_read(XBT_NIL, path, &res);
> +             if (msg)
> +                     return msg;
> +
> +             rs = (XenbusState)(res[0] - 48);
> +             free(res);
> +
> +             if (rs == *state) {
> +                     wait_event_timeout(NULL, false, WAIT_XENBUS_POLL_TO_MS);
> +             } else {
> +                     *state = rs;
> +                     break;
> +             }
> +     }
> +     return NULL;
> +}
> +
> +/* Send data to xenbus.  This can block.  All of the requests are seen
> + * by xenbus as if sent atomically.  The header is added
> + * automatically, using type %type, req_id %req_id, and trans_id
> + * %trans_id.
> + */
> +static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
> +                  const struct write_req *req, int nr_reqs)
> +{
> +     XENSTORE_RING_IDX prod;
> +     int r;
> +     int len = 0;
> +     const struct write_req *cur_req;
> +     int req_off;
> +     int total_off;
> +     int this_chunk;
> +     struct xsd_sockmsg m = {
> +             .type = type,
> +             .req_id = req_id,
> +             .tx_id = trans_id
> +     };
> +     struct write_req header_req = {
> +             &m,
> +             sizeof(m)
> +     };
> +
> +     for (r = 0; r < nr_reqs; r++)
> +             len += req[r].len;
> +     m.len = len;
> +     len += sizeof(m);
> +
> +     cur_req = &header_req;
> +
> +     BUG_ON(len > XENSTORE_RING_SIZE);
> +     prod = xenstore_buf->req_prod;
> +     /* We are running synchronously, so it is a bug if we do not
> +      * have enough room to send a message: please note that a message
> +      * can occupy multiple slots in the ring buffer.
> +      */
> +     BUG_ON(prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE);
> +
> +     total_off = 0;
> +     req_off = 0;
> +     while (total_off < len) {
> +             this_chunk = min(cur_req->len - req_off,
> +                              XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
> +             memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
> +                    (char *)cur_req->data + req_off, this_chunk);
> +             prod += this_chunk;
> +             req_off += this_chunk;
> +             total_off += this_chunk;
> +             if (req_off == cur_req->len) {
> +                     req_off = 0;
> +                     if (cur_req == &header_req)
> +                             cur_req = req;
> +                     else
> +                             cur_req++;
> +             }
> +     }
> +
> +     BUG_ON(req_off != 0);
> +     BUG_ON(total_off != len);
> +     BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
> +
> +     /* Remote must see entire message before updating indexes */
> +     wmb();
> +
> +     xenstore_buf->req_prod += len;
> +
> +     /* Send evtchn to notify remote */
> +     notify_remote_via_evtchn(xenbus_evtchn);
> +}
> +
> +/* Send a message to xenbus, in the same fashion as xb_write, and
> + * block waiting for a reply.  The reply is malloced and should be
> + * freed by the caller.
> + */
> +struct xsd_sockmsg *xenbus_msg_reply(int type,
> +                                  xenbus_transaction_t trans,
> +                                  struct write_req *io,
> +                                  int nr_reqs)
> +{
> +     struct xsd_sockmsg *rep;
> +
> +     /* We do not use request identifier which is echoed in daemon's 
> response. */
> +     xb_write(type, 0, trans, io, nr_reqs);
> +     /* Now wait for the message to arrive. */
> +     if (!xenbus_get_reply(&rep))
> +             return NULL;
> +     return rep;
> +}
> +
> +static char *errmsg(struct xsd_sockmsg *rep)
> +{
> +     char *res;
> +
> +     if (!rep) {
> +             char msg[] = "No reply";
> +             size_t len = strlen(msg) + 1;
> +
> +             return memcpy(malloc(len), msg, len);
> +     }
> +     if (rep->type != XS_ERROR)
> +             return NULL;
> +     res = malloc(rep->len + 1);
> +     memcpy(res, rep + 1, rep->len);
> +     res[rep->len] = 0;
> +     free(rep);
> +     return res;
> +}
> +
> +/* List the contents of a directory.  Returns a malloc()ed array of
> + * pointers to malloc()ed strings.  The array is NULL terminated.  May
> + * block.
> + */
> +char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
> +{
> +     struct xsd_sockmsg *reply, *repmsg;
> +     struct write_req req[] = { { pre, strlen(pre) + 1 } };
> +     int nr_elems, x, i;
> +     char **res, *msg;
> +
> +     repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
> +     msg = errmsg(repmsg);
> +     if (msg) {
> +             *contents = NULL;
> +             return msg;
> +     }
> +     reply = repmsg + 1;
> +     for (x = nr_elems = 0; x < repmsg->len; x++)
> +             nr_elems += (((char *)reply)[x] == 0);
> +     res = malloc(sizeof(res[0]) * (nr_elems + 1));
> +     for (x = i = 0; i < nr_elems; i++) {
> +             int l = strlen((char *)reply + x);
> +
> +             res[i] = malloc(l + 1);
> +             memcpy(res[i], (char *)reply + x, l + 1);
> +             x += l + 1;
> +     }
> +     res[i] = NULL;
> +     free(repmsg);
> +     *contents = res;
> +     return NULL;
> +}
> +
> +char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
> +{
> +     struct write_req req[] = { {path, strlen(path) + 1} };
> +     struct xsd_sockmsg *rep;
> +     char *res, *msg;
> +
> +     rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
> +     msg = errmsg(rep);
> +     if (msg) {
> +             *value = NULL;
> +             return msg;
> +     }
> +     res = malloc(rep->len + 1);
> +     memcpy(res, rep + 1, rep->len);
> +     res[rep->len] = 0;
> +     free(rep);
> +     *value = res;
> +     return NULL;
> +}
> +
> +char *xenbus_write(xenbus_transaction_t xbt, const char *path,
> +                                const char *value)
> +{
> +     struct write_req req[] = {
> +             {path, strlen(path) + 1},
> +             {value, strlen(value)},
> +     };
> +     struct xsd_sockmsg *rep;
> +     char *msg;
> +
> +     rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
> +     msg = errmsg(rep);
> +     if (msg)
> +             return msg;
> +     free(rep);
> +     return NULL;
> +}
> +
> +char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
> +{
> +     struct write_req req[] = { {path, strlen(path) + 1} };
> +     struct xsd_sockmsg *rep;
> +     char *msg;
> +
> +     rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
> +     msg = errmsg(rep);
> +     if (msg)
> +             return msg;
> +     free(rep);
> +     return NULL;
> +}
> +
> +char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char 
> **value)
> +{
> +     struct write_req req[] = { {path, strlen(path) + 1} };
> +     struct xsd_sockmsg *rep;
> +     char *res, *msg;
> +
> +     rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
> +     msg = errmsg(rep);
> +     if (msg) {
> +             *value = NULL;
> +             return msg;
> +     }
> +     res = malloc(rep->len + 1);
> +     memcpy(res, rep + 1, rep->len);
> +     res[rep->len] = 0;
> +     free(rep);
> +     *value = res;
> +     return NULL;
> +}
> +
> +#define PERM_MAX_SIZE 32
> +char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path,
> +                    domid_t dom, char perm)
> +{
> +     char value[PERM_MAX_SIZE];
> +     struct write_req req[] = {
> +             {path, strlen(path) + 1},
> +             {value, 0},
> +     };
> +     struct xsd_sockmsg *rep;
> +     char *msg;
> +
> +     snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
> +     req[1].len = strlen(value) + 1;
> +     rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
> +     msg = errmsg(rep);
> +     if (msg)
> +             return msg;
> +     free(rep);
> +     return NULL;
> +}
> +
> +char *xenbus_transaction_start(xenbus_transaction_t *xbt)
> +{
> +     /* Xenstored becomes angry if you send a length 0 message, so just
> +      * shove a nul terminator on the end
> +      */
> +     struct write_req req = { "", 1};
> +     struct xsd_sockmsg *rep;
> +     char *err;
> +
> +     rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
> +     err = errmsg(rep);
> +     if (err)
> +             return err;
> +     sscanf((char *)(rep + 1), "%lu", xbt);
> +     free(rep);
> +     return NULL;
> +}
> +
> +char *xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
> +{
> +     struct xsd_sockmsg *rep;
> +     struct write_req req;
> +     char *err;
> +
> +     *retry = 0;
> +
> +     req.data = abort ? "F" : "T";
> +     req.len = 2;
> +     rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
> +     err = errmsg(rep);
> +     if (err) {
> +             if (!strcmp(err, "EAGAIN")) {
> +                     *retry = 1;
> +                     free(err);
> +                     return NULL;
> +             } else {
> +                     return err;
> +             }
> +     }
> +     free(rep);
> +     return NULL;
> +}
> +
> +int xenbus_read_integer(const char *path)
> +{
> +     char *res, *buf;
> +     int t;
> +
> +     res = xenbus_read(XBT_NIL, path, &buf);
> +     if (res) {
> +             printk("Failed to read %s.\n", path);
> +             free(res);
> +             return -1;
> +     }
> +     sscanf(buf, "%d", &t);
> +     free(buf);
> +     return t;
> +}
> +
> +int xenbus_read_uuid(const char *path, unsigned char uuid[16]) {
> +     char *res, *buf;
> +
> +     res = xenbus_read(XBT_NIL, path, &buf);
> +     if (res) {
> +             printk("Failed to read %s.\n", path);
> +             free(res);
> +             return 0;
> +     }
> +     if (strlen(buf) != ((2 * 16) + 4) /* 16 hex bytes and 4 hyphens */
> +         || sscanf(buf,
> +                   "%2hhx%2hhx%2hhx%2hhx-"
> +                   "%2hhx%2hhx-"
> +                   "%2hhx%2hhx-"
> +                   "%2hhx%2hhx-"
> +                   "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
> +                   uuid, uuid + 1, uuid + 2, uuid + 3,
> +                   uuid + 4, uuid + 5, uuid + 6, uuid + 7,
> +                   uuid + 8, uuid + 9, uuid + 10, uuid + 11,
> +                   uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) {
> +             printk("Xenbus path %s value %s is not a uuid!\n", path, buf);
> +             free(buf);
> +             return 0;
> +     }
> +     free(buf);
> +     return 1;
> +}
> +
> +char *xenbus_printf(xenbus_transaction_t xbt,
> +                 const char *node, const char *path,
> +                 const char *fmt, ...)
> +{
> +#define BUFFER_SIZE 256
> +     char fullpath[BUFFER_SIZE];
> +     char val[BUFFER_SIZE];
> +     va_list args;
> +
> +     BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
> +     sprintf(fullpath, "%s/%s", node, path);
> +     va_start(args, fmt);
> +     vsprintf(val, fmt, args);
> +     va_end(args);
> +     return xenbus_write(xbt, fullpath, val);
> +}
> +
> +domid_t xenbus_get_self_id(void)
> +{
> +     char *dom_id;
> +     domid_t ret;
> +
> +     BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
> +     sscanf(dom_id, "%"SCNd16, &ret);
> +
> +     return ret;
> +}
> +
> +void init_xenbus(void)
> +{
> +     u64 v;
> +
> +     debug("%s\n", __func__);
> +     if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v))
> +             BUG();
> +     xenbus_evtchn = v;
> +
> +     if (hvm_get_parameter(HVM_PARAM_STORE_PFN, &v))
> +             BUG();
> +     xenstore_buf = (struct xenstore_domain_interface *)map_frame_virt(v);
> +}
> +
> +void fini_xenbus(void)
> +{
> +     debug("%s\n", __func__);
> +}
> diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h
> new file mode 100644
> index 0000000000..e2e3ef9292
> --- /dev/null
> +++ b/include/xen/xenbus.h
> @@ -0,0 +1,86 @@
> +#ifndef XENBUS_H__
> +#define XENBUS_H__
> +
> +#include <xen/interface/xen.h>
> +#include <xen/interface/io/xenbus.h>
> +
> +typedef unsigned long xenbus_transaction_t;
> +#define XBT_NIL ((xenbus_transaction_t)0)
> +
> +extern u32 xenbus_evtchn;
> +
> +/* Initialize the XenBus system. */
> +void init_xenbus(void);
> +/* Finalize the XenBus system. */
> +void fini_xenbus(void);
> +
> +/* Read the value associated with a path.  Returns a malloc'd error
> + * string on failure and sets *value to NULL.  On success, *value is
> + * set to a malloc'd copy of the value.
> + */
> +char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
> +
> +char *xenbus_wait_for_state_change(const char *path, XenbusState *state);
> +char *xenbus_switch_state(xenbus_transaction_t xbt, const char *path,
> +                       XenbusState state);
> +
> +/* Associates a value with a path.  Returns a malloc'd error string on
> + * failure.
> + */
> +char *xenbus_write(xenbus_transaction_t xbt, const char *path,
> +                const char *value);
> +
> +/* Removes the value associated with a path.  Returns a malloc'd error
> + * string on failure.
> + */
> +char *xenbus_rm(xenbus_transaction_t xbt, const char *path);
> +
> +/* List the contents of a directory.  Returns a malloc'd error string
> + * on failure and sets *contents to NULL.  On success, *contents is
> + * set to a malloc'd array of pointers to malloc'd strings.  The array
> + * is NULL terminated.  May block.
> + */
> +char *xenbus_ls(xenbus_transaction_t xbt, const char *prefix, char 
> ***contents);
> +
> +/* Reads permissions associated with a path.  Returns a malloc'd error
> + * string on failure and sets *value to NULL.  On success, *value is
> + * set to a malloc'd copy of the value.
> + */
> +char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char 
> **value);
> +
> +/* Sets the permissions associated with a path.  Returns a malloc'd
> + * error string on failure.
> + */
> +char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path, domid_t 
> dom,
> +                    char perm);
> +
> +/* Start a xenbus transaction.  Returns the transaction in xbt on
> + * success or a malloc'd error string otherwise.
> + */
> +char *xenbus_transaction_start(xenbus_transaction_t *xbt);
> +
> +/* End a xenbus transaction.  Returns a malloc'd error string if it
> + * fails.  abort says whether the transaction should be aborted.
> + * Returns 1 in *retry iff the transaction should be retried.
> + */
> +char *xenbus_transaction_end(xenbus_transaction_t, int abort,
> +                          int *retry);
> +
> +/* Read path and parse it as an integer.  Returns -1 on error. */
> +int xenbus_read_integer(const char *path);
> +
> +/* Read path and parse it as 16 byte uuid. Returns 1 if
> + * read and parsing were successful, 0 if not
> + */
> +int xenbus_read_uuid(const char *path, unsigned char uuid[16]);
> +
> +/* Contraction of snprintf and xenbus_write(path/node). */
> +char *xenbus_printf(xenbus_transaction_t xbt,
> +                 const char *node, const char *path,
> +                 const char *fmt, ...)
> +     __attribute__((__format__(printf, 4, 5)));
> +
> +/* Utility function to figure out our domain id */
> +domid_t xenbus_get_self_id(void);
> +
> +#endif /* XENBUS_H__ */
>

Reply via email to