1// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) 2006 - Cambridge University
4 * (C) 2020 - EPAM Systems Inc.
5 *
6 * File: xenbus.c [1]
7 * Author: Steven Smith (sos22@cam.ac.uk)
8 * Changes: Grzegorz Milos (gm281@cam.ac.uk)
9 * Changes: John D. Ramsdell
10 *
11 * Date: Jun 2006, changes Aug 2006
12 *
13 * Description: Minimal implementation of xenbus
14 *
15 * [1] - http://xenbits.xen.org/gitweb/?p=mini-os.git;a=summary
16 */
17
18#include <common.h>
19#include <log.h>
20
21#include <asm/armv8/mmu.h>
22#include <asm/io.h>
23#include <asm/xen/system.h>
24
25#include <linux/bug.h>
26#include <linux/compat.h>
27
28#include <xen/events.h>
29#include <xen/hvm.h>
30#include <xen/xenbus.h>
31
32#include <xen/interface/io/xs_wire.h>
33
34#define map_frame_virt(v)	(v << PAGE_SHIFT)
35
36#define SCNd16			"d"
37
38/* Wait for reply time out, ms */
39#define WAIT_XENBUS_TO_MS	5000
40/* Polling time out, ms */
41#define WAIT_XENBUS_POLL_TO_MS	1
42
43static struct xenstore_domain_interface *xenstore_buf;
44
45static char *errmsg(struct xsd_sockmsg *rep);
46
47u32 xenbus_evtchn;
48
49struct write_req {
50	const void *data;
51	unsigned int len;
52};
53
54static void memcpy_from_ring(const void *r, void *d, int off, int len)
55{
56	int c1, c2;
57	const char *ring = r;
58	char *dest = d;
59
60	c1 = min(len, XENSTORE_RING_SIZE - off);
61	c2 = len - c1;
62	memcpy(dest, ring + off, c1);
63	memcpy(dest + c1, ring, c2);
64}
65
66/**
67 * xenbus_get_reply() - Receive reply from xenbus
68 * @req_reply: reply message structure
69 *
70 * Wait for reply message event from the ring and copy received message
71 * to input xsd_sockmsg structure. Repeat until full reply is
72 * proceeded.
73 *
74 * Return: false - timeout
75 *	   true - reply is received
76 */
77static bool xenbus_get_reply(struct xsd_sockmsg **req_reply)
78{
79	struct xsd_sockmsg msg;
80	unsigned int prod = xenstore_buf->rsp_prod;
81
82again:
83	if (!wait_event_timeout(NULL, prod != xenstore_buf->rsp_prod,
84				WAIT_XENBUS_TO_MS)) {
85		printk("%s: wait_event timeout\n", __func__);
86		return false;
87	}
88
89	prod = xenstore_buf->rsp_prod;
90	if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg))
91		goto again;
92
93	rmb();
94	memcpy_from_ring(xenstore_buf->rsp, &msg,
95			 MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
96			 sizeof(msg));
97
98	if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(msg) + msg.len)
99		goto again;
100
101	/* We do not support and expect any Xen bus wathes. */
102	BUG_ON(msg.type == XS_WATCH_EVENT);
103
104	*req_reply = malloc(sizeof(msg) + msg.len);
105	memcpy_from_ring(xenstore_buf->rsp, *req_reply,
106			 MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
107			 msg.len + sizeof(msg));
108	mb();
109	xenstore_buf->rsp_cons += msg.len + sizeof(msg);
110
111	wmb();
112	notify_remote_via_evtchn(xenbus_evtchn);
113	return true;
114}
115
116char *xenbus_switch_state(xenbus_transaction_t xbt, const char *path,
117			  XenbusState state)
118{
119	char *current_state;
120	char *msg = NULL;
121	char *msg2 = NULL;
122	char value[2];
123	XenbusState rs;
124	int xbt_flag = 0;
125	int retry = 0;
126
127	do {
128		if (xbt == XBT_NIL) {
129			msg = xenbus_transaction_start(&xbt);
130			if (msg)
131				goto exit;
132			xbt_flag = 1;
133		}
134
135		msg = xenbus_read(xbt, path, &current_state);
136		if (msg)
137			goto exit;
138
139		rs = (XenbusState)(current_state[0] - '0');
140		free(current_state);
141		if (rs == state) {
142			msg = NULL;
143			goto exit;
144		}
145
146		snprintf(value, 2, "%d", state);
147		msg = xenbus_write(xbt, path, value);
148
149exit:
150		if (xbt_flag) {
151			msg2 = xenbus_transaction_end(xbt, 0, &retry);
152			xbt = XBT_NIL;
153		}
154		if (msg == NULL && msg2 != NULL)
155			msg = msg2;
156		else
157			free(msg2);
158	} while (retry);
159
160	return msg;
161}
162
163char *xenbus_wait_for_state_change(const char *path, XenbusState *state)
164{
165	for (;;) {
166		char *res, *msg;
167		XenbusState rs;
168
169		msg = xenbus_read(XBT_NIL, path, &res);
170		if (msg)
171			return msg;
172
173		rs = (XenbusState)(res[0] - 48);
174		free(res);
175
176		if (rs == *state) {
177			wait_event_timeout(NULL, false, WAIT_XENBUS_POLL_TO_MS);
178		} else {
179			*state = rs;
180			break;
181		}
182	}
183	return NULL;
184}
185
186/* Send data to xenbus.  This can block.  All of the requests are seen
187 * by xenbus as if sent atomically.  The header is added
188 * automatically, using type %type, req_id %req_id, and trans_id
189 * %trans_id.
190 */
191static void xb_write(int type, int req_id, xenbus_transaction_t trans_id,
192		     const struct write_req *req, int nr_reqs)
193{
194	XENSTORE_RING_IDX prod;
195	int r;
196	int len = 0;
197	const struct write_req *cur_req;
198	int req_off;
199	int total_off;
200	int this_chunk;
201	struct xsd_sockmsg m = {
202		.type = type,
203		.req_id = req_id,
204		.tx_id = trans_id
205	};
206	struct write_req header_req = {
207		&m,
208		sizeof(m)
209	};
210
211	for (r = 0; r < nr_reqs; r++)
212		len += req[r].len;
213	m.len = len;
214	len += sizeof(m);
215
216	cur_req = &header_req;
217
218	BUG_ON(len > XENSTORE_RING_SIZE);
219	prod = xenstore_buf->req_prod;
220	/* We are running synchronously, so it is a bug if we do not
221	 * have enough room to send a message: please note that a message
222	 * can occupy multiple slots in the ring buffer.
223	 */
224	BUG_ON(prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE);
225
226	total_off = 0;
227	req_off = 0;
228	while (total_off < len) {
229		this_chunk = min(cur_req->len - req_off,
230				 XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod));
231		memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod),
232		       (char *)cur_req->data + req_off, this_chunk);
233		prod += this_chunk;
234		req_off += this_chunk;
235		total_off += this_chunk;
236		if (req_off == cur_req->len) {
237			req_off = 0;
238			if (cur_req == &header_req)
239				cur_req = req;
240			else
241				cur_req++;
242		}
243	}
244
245	BUG_ON(req_off != 0);
246	BUG_ON(total_off != len);
247	BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE);
248
249	/* Remote must see entire message before updating indexes */
250	wmb();
251
252	xenstore_buf->req_prod += len;
253
254	/* Send evtchn to notify remote */
255	notify_remote_via_evtchn(xenbus_evtchn);
256}
257
258/* Send a message to xenbus, in the same fashion as xb_write, and
259 * block waiting for a reply.  The reply is malloced and should be
260 * freed by the caller.
261 */
262struct xsd_sockmsg *xenbus_msg_reply(int type,
263				     xenbus_transaction_t trans,
264				     struct write_req *io,
265				     int nr_reqs)
266{
267	struct xsd_sockmsg *rep;
268
269	/* We do not use request identifier which is echoed in daemon's response. */
270	xb_write(type, 0, trans, io, nr_reqs);
271	/* Now wait for the message to arrive. */
272	if (!xenbus_get_reply(&rep))
273		return NULL;
274	return rep;
275}
276
277static char *errmsg(struct xsd_sockmsg *rep)
278{
279	char *res;
280
281	if (!rep) {
282		char msg[] = "No reply";
283		size_t len = strlen(msg) + 1;
284
285		return memcpy(malloc(len), msg, len);
286	}
287	if (rep->type != XS_ERROR)
288		return NULL;
289	res = malloc(rep->len + 1);
290	memcpy(res, rep + 1, rep->len);
291	res[rep->len] = 0;
292	free(rep);
293	return res;
294}
295
296/* List the contents of a directory.  Returns a malloc()ed array of
297 * pointers to malloc()ed strings.  The array is NULL terminated.  May
298 * block.
299 */
300char *xenbus_ls(xenbus_transaction_t xbt, const char *pre, char ***contents)
301{
302	struct xsd_sockmsg *reply, *repmsg;
303	struct write_req req[] = { { pre, strlen(pre) + 1 } };
304	int nr_elems, x, i;
305	char **res, *msg;
306
307	repmsg = xenbus_msg_reply(XS_DIRECTORY, xbt, req, ARRAY_SIZE(req));
308	msg = errmsg(repmsg);
309	if (msg) {
310		*contents = NULL;
311		return msg;
312	}
313	reply = repmsg + 1;
314	for (x = nr_elems = 0; x < repmsg->len; x++)
315		nr_elems += (((char *)reply)[x] == 0);
316	res = malloc(sizeof(res[0]) * (nr_elems + 1));
317	for (x = i = 0; i < nr_elems; i++) {
318		int l = strlen((char *)reply + x);
319
320		res[i] = malloc(l + 1);
321		memcpy(res[i], (char *)reply + x, l + 1);
322		x += l + 1;
323	}
324	res[i] = NULL;
325	free(repmsg);
326	*contents = res;
327	return NULL;
328}
329
330char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value)
331{
332	struct write_req req[] = { {path, strlen(path) + 1} };
333	struct xsd_sockmsg *rep;
334	char *res, *msg;
335
336	rep = xenbus_msg_reply(XS_READ, xbt, req, ARRAY_SIZE(req));
337	msg = errmsg(rep);
338	if (msg) {
339		*value = NULL;
340		return msg;
341	}
342	res = malloc(rep->len + 1);
343	memcpy(res, rep + 1, rep->len);
344	res[rep->len] = 0;
345	free(rep);
346	*value = res;
347	return NULL;
348}
349
350char *xenbus_write(xenbus_transaction_t xbt, const char *path,
351				   const char *value)
352{
353	struct write_req req[] = {
354		{path, strlen(path) + 1},
355		{value, strlen(value)},
356	};
357	struct xsd_sockmsg *rep;
358	char *msg;
359
360	rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
361	msg = errmsg(rep);
362	if (msg)
363		return msg;
364	free(rep);
365	return NULL;
366}
367
368char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
369{
370	struct write_req req[] = { {path, strlen(path) + 1} };
371	struct xsd_sockmsg *rep;
372	char *msg;
373
374	rep = xenbus_msg_reply(XS_RM, xbt, req, ARRAY_SIZE(req));
375	msg = errmsg(rep);
376	if (msg)
377		return msg;
378	free(rep);
379	return NULL;
380}
381
382char *xenbus_get_perms(xenbus_transaction_t xbt, const char *path, char **value)
383{
384	struct write_req req[] = { {path, strlen(path) + 1} };
385	struct xsd_sockmsg *rep;
386	char *res, *msg;
387
388	rep = xenbus_msg_reply(XS_GET_PERMS, xbt, req, ARRAY_SIZE(req));
389	msg = errmsg(rep);
390	if (msg) {
391		*value = NULL;
392		return msg;
393	}
394	res = malloc(rep->len + 1);
395	memcpy(res, rep + 1, rep->len);
396	res[rep->len] = 0;
397	free(rep);
398	*value = res;
399	return NULL;
400}
401
402#define PERM_MAX_SIZE 32
403char *xenbus_set_perms(xenbus_transaction_t xbt, const char *path,
404		       domid_t dom, char perm)
405{
406	char value[PERM_MAX_SIZE];
407	struct write_req req[] = {
408		{path, strlen(path) + 1},
409		{value, 0},
410	};
411	struct xsd_sockmsg *rep;
412	char *msg;
413
414	snprintf(value, PERM_MAX_SIZE, "%c%hu", perm, dom);
415	req[1].len = strlen(value) + 1;
416	rep = xenbus_msg_reply(XS_SET_PERMS, xbt, req, ARRAY_SIZE(req));
417	msg = errmsg(rep);
418	if (msg)
419		return msg;
420	free(rep);
421	return NULL;
422}
423
424char *xenbus_transaction_start(xenbus_transaction_t *xbt)
425{
426	/* Xenstored becomes angry if you send a length 0 message, so just
427	 * shove a nul terminator on the end
428	 */
429	struct write_req req = { "", 1};
430	struct xsd_sockmsg *rep;
431	char *err;
432
433	rep = xenbus_msg_reply(XS_TRANSACTION_START, 0, &req, 1);
434	err = errmsg(rep);
435	if (err)
436		return err;
437	sscanf((char *)(rep + 1), "%lu", xbt);
438	free(rep);
439	return NULL;
440}
441
442char *xenbus_transaction_end(xenbus_transaction_t t, int abort, int *retry)
443{
444	struct xsd_sockmsg *rep;
445	struct write_req req;
446	char *err;
447
448	*retry = 0;
449
450	req.data = abort ? "F" : "T";
451	req.len = 2;
452	rep = xenbus_msg_reply(XS_TRANSACTION_END, t, &req, 1);
453	err = errmsg(rep);
454	if (err) {
455		if (!strcmp(err, "EAGAIN")) {
456			*retry = 1;
457			free(err);
458			return NULL;
459		} else {
460			return err;
461		}
462	}
463	free(rep);
464	return NULL;
465}
466
467int xenbus_read_integer(const char *path)
468{
469	char *res, *buf;
470	int t;
471
472	res = xenbus_read(XBT_NIL, path, &buf);
473	if (res) {
474		printk("Failed to read %s.\n", path);
475		free(res);
476		return -1;
477	}
478	sscanf(buf, "%d", &t);
479	free(buf);
480	return t;
481}
482
483int xenbus_read_uuid(const char *path, unsigned char uuid[16])
484{
485	char *res, *buf;
486
487	res = xenbus_read(XBT_NIL, path, &buf);
488	if (res) {
489		printk("Failed to read %s.\n", path);
490		free(res);
491		return 0;
492	}
493	if (strlen(buf) != ((2 * 16) + 4) /* 16 hex bytes and 4 hyphens */
494	    || sscanf(buf,
495		      "%2hhx%2hhx%2hhx%2hhx-"
496		      "%2hhx%2hhx-"
497		      "%2hhx%2hhx-"
498		      "%2hhx%2hhx-"
499		      "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
500		      uuid, uuid + 1, uuid + 2, uuid + 3,
501		      uuid + 4, uuid + 5, uuid + 6, uuid + 7,
502		      uuid + 8, uuid + 9, uuid + 10, uuid + 11,
503		      uuid + 12, uuid + 13, uuid + 14, uuid + 15) != 16) {
504		printk("Xenbus path %s value %s is not a uuid!\n", path, buf);
505		free(buf);
506		return 0;
507	}
508	free(buf);
509	return 1;
510}
511
512char *xenbus_printf(xenbus_transaction_t xbt,
513		    const char *node, const char *path,
514		    const char *fmt, ...)
515{
516#define BUFFER_SIZE 256
517	char fullpath[BUFFER_SIZE];
518	char val[BUFFER_SIZE];
519	va_list args;
520
521	BUG_ON(strlen(node) + strlen(path) + 1 >= BUFFER_SIZE);
522	sprintf(fullpath, "%s/%s", node, path);
523	va_start(args, fmt);
524	vsprintf(val, fmt, args);
525	va_end(args);
526	return xenbus_write(xbt, fullpath, val);
527}
528
529domid_t xenbus_get_self_id(void)
530{
531	char *dom_id;
532	domid_t ret;
533
534	BUG_ON(xenbus_read(XBT_NIL, "domid", &dom_id));
535	sscanf(dom_id, "%"SCNd16, &ret);
536
537	return ret;
538}
539
540void init_xenbus(void)
541{
542	u64 v;
543
544	debug("%s\n", __func__);
545	if (hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v))
546		BUG();
547	xenbus_evtchn = v;
548
549	if (hvm_get_parameter(HVM_PARAM_STORE_PFN, &v))
550		BUG();
551	xenstore_buf = (struct xenstore_domain_interface *)map_frame_virt(v);
552}
553
554void fini_xenbus(void)
555{
556	debug("%s\n", __func__);
557}
558