[PATCH 10/17] xen: Port Xen bus driver from mini-os
Heinrich Schuchardt
xypron.glpk at gmx.de
Thu Jul 2 06:43:41 CEST 2020
On 7/1/20 6:29 PM, Anastasiia Lukianenko wrote:
> From: Oleksandr Andrushchenko <oleksandr_andrushchenko at epam.com>
>
> Make required updates to run on u-boot and strip test code.
>
> Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko at epam.com>
> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko at 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 (sos22 at cam.ac.uk)
> + * Changes: Grzegorz Milos (gm281 at 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, ¤t_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__ */
>
More information about the U-Boot
mailing list