mirror of
				https://source.denx.de/u-boot/u-boot.git
				synced 2025-11-03 18:01:41 +01:00 
			
		
		
		
	Make required updates to run on u-boot and strip test code. Signed-off-by: Anastasiia Lukianenko <anastasiia_lukianenko@epam.com> Signed-off-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
		
			
				
	
	
		
			558 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			558 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
/*
 | 
						|
 * (C) 2006 - Cambridge University
 | 
						|
 * (C) 2020 - EPAM Systems Inc.
 | 
						|
 *
 | 
						|
 * File: xenbus.c [1]
 | 
						|
 * Author: Steven Smith (sos22@cam.ac.uk)
 | 
						|
 * Changes: Grzegorz Milos (gm281@cam.ac.uk)
 | 
						|
 * Changes: John D. Ramsdell
 | 
						|
 *
 | 
						|
 * Date: Jun 2006, changes Aug 2006
 | 
						|
 *
 | 
						|
 * Description: Minimal implementation of xenbus
 | 
						|
 *
 | 
						|
 * [1] - http://xenbits.xen.org/gitweb/?p=mini-os.git;a=summary
 | 
						|
 */
 | 
						|
 | 
						|
#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);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * xenbus_get_reply() - Receive reply from xenbus
 | 
						|
 * @req_reply: reply message structure
 | 
						|
 *
 | 
						|
 * Wait for reply message event from the ring and copy received message
 | 
						|
 * to input xsd_sockmsg structure. Repeat until full reply is
 | 
						|
 * proceeded.
 | 
						|
 *
 | 
						|
 * Return: false - timeout
 | 
						|
 *	   true - reply is received
 | 
						|
 */
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
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__);
 | 
						|
}
 |