[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, &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__ */
>



More information about the U-Boot mailing list