diff -rupN xen-3.1.0-src.orig/Config.mk xen-3.1.0-src.new/Config.mk
--- xen-3.1.0-src.orig/Config.mk 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/Config.mk 2007-08-23 11:05:41.000000000 -0400
@@ -90,7 +90,6 @@ ACM_DEFAULT_SECURITY_POLICY ?= ACM_NULL_
XENSTAT_XENTOP ?= y
VTPM_TOOLS ?= n
LIBXENAPI_BINDINGS ?= n
-XENFB_TOOLS ?= n
PYTHON_TOOLS ?= y
-include $(XEN_ROOT)/.config
diff -rupN xen-3.1.0-src.orig/tools/check/check_libvncserver xen-3.1.0-src.new/tools/check/check_libvncserver
--- xen-3.1.0-src.orig/tools/check/check_libvncserver 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/check/check_libvncserver 1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-#!/bin/sh
-# CHECK-BUILD CHECK-INSTALL
-
-if [ ! "$XENFB_TOOLS" = "y" ]
-then
- echo -n "unused, "
- exit 0
-fi
-
-RC=0
-
-LIBVNCSERVER_CONFIG="$(which libvncserver-config)"
-
-if test -z ${LIBVNCSERVER_CONFIG}; then
- RC=1
-else
- ${LIBVNCSERVER_CONFIG} --libs 2>&1 > /dev/null
- RC=$?
-fi
-
-if test $RC -ne 0; then
- echo "FAILED"
- echo " *** libvncserver-config is missing. "
- echo " *** Please install libvncserver."
-fi
-
-exit $RC
diff -rupN xen-3.1.0-src.orig/tools/check/check_sdl xen-3.1.0-src.new/tools/check/check_sdl
--- xen-3.1.0-src.orig/tools/check/check_sdl 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/check/check_sdl 1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-#!/bin/sh
-# CHECK-BUILD CHECK-INSTALL
-
-if [ ! "$XENFB_TOOLS" = "y" ]
-then
- echo -n "unused, "
- exit 0
-fi
-
-RC=0
-
-SDL_CONFIG="$(which sdl-config)"
-
-if test -z ${SDL_CONFIG}; then
- RC=1
-else
- ${SDL_CONFIG} --libs 2>&1 > /dev/null
- RC=$?
-fi
-
-if test $RC -ne 0; then
- echo "FAILED"
- echo " *** sdl-config is missing. "
- echo " *** Please install libsdl-dev or sdl."
-fi
-
-exit $RC
diff -rupN xen-3.1.0-src.orig/tools/check/Makefile xen-3.1.0-src.new/tools/check/Makefile
--- xen-3.1.0-src.orig/tools/check/Makefile 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/check/Makefile 2007-08-23 11:06:47.000000000 -0400
@@ -7,7 +7,7 @@ all: build
# Check this machine is OK for building on.
.PHONY: build
build:
- XENFB_TOOLS=$(XENFB_TOOLS) ./chk build
+ ./chk build
# Check this machine is OK for installing on.
# DO NOT use this check from 'make install' in the parent
@@ -15,7 +15,7 @@ build:
# copy rather than actually installing.
.PHONY: install
install:
- XENFB_TOOLS=$(XENFB_TOOLS) ./chk install
+ ./chk install
.PHONY: clean
clean:
diff -rupN xen-3.1.0-src.orig/tools/ioemu/hw/xenfb.c xen-3.1.0-src.new/tools/ioemu/hw/xenfb.c
--- xen-3.1.0-src.orig/tools/ioemu/hw/xenfb.c 1969-12-31 19:00:00.000000000 -0500
+++ xen-3.1.0-src.new/tools/ioemu/hw/xenfb.c 2007-08-23 11:05:47.000000000 -0400
@@ -0,0 +1,825 @@
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <xenctrl.h>
+#include <xen/io/xenbus.h>
+#include <xen/io/fbif.h>
+#include <xen/io/kbdif.h>
+#include <xen/io/protocols.h>
+#include <sys/select.h>
+#include <stdbool.h>
+#include <xen/event_channel.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <xs.h>
+
+#include "xenfb.h"
+
+// FIXME defend against malicious frontend?
+
+struct xenfb_device {
+ const char *devicetype;
+ char nodename[64]; /* backend xenstore dir */
+ char otherend[64]; /* frontend xenstore dir */
+ int otherend_id; /* frontend domid */
+ enum xenbus_state state; /* backend state */
+ void *page; /* shared page */
+ evtchn_port_t port;
+ struct xenfb_private *xenfb;
+};
+
+struct xenfb_private {
+ struct xenfb pub;
+ int evt_xch; /* event channel driver handle */
+ int xc; /* hypervisor interface handle */
+ struct xs_handle *xsh; /* xs daemon handle */
+ struct xenfb_device fb, kbd;
+ size_t fb_len; /* size of framebuffer */
+ char protocol[64]; /* frontend protocol */
+};
+
+static void xenfb_detach_dom(struct xenfb_private *);
+
+static char *xenfb_path_in_dom(struct xs_handle *xsh,
+ char *buf, size_t size,
+ unsigned domid, const char *fmt, ...)
+{
+ va_list ap;
+ char *domp = xs_get_domain_path(xsh, domid);
+ int n;
+
+ if (domp == NULL)
+ return NULL;
+
+ n = snprintf(buf, size, "%s/", domp);
+ free(domp);
+ if (n >= size)
+ return NULL;
+
+ va_start(ap, fmt);
+ n += vsnprintf(buf + n, size - n, fmt, ap);
+ va_end(ap);
+ if (n >= size)
+ return NULL;
+
+ return buf;
+}
+
+static int xenfb_xs_scanf1(struct xs_handle *xsh,
+ const char *dir, const char *node,
+ const char *fmt, void *dest)
+{
+ char buf[1024];
+ char *p;
+ int ret;
+
+ if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) {
+ errno = ENOENT;
+ return -1;
+ }
+ p = xs_read(xsh, XBT_NULL, buf, NULL);
+ if (!p) {
+ errno = ENOENT;
+ return -1;
+ }
+ ret = sscanf(p, fmt, dest);
+ free(p);
+ if (ret != 1) {
+ errno = EDOM;
+ return -1;
+ }
+ return ret;
+}
+
+static int xenfb_xs_printf(struct xs_handle *xsh,
+ const char *dir, const char *node, char *fmt, ...)
+{
+ va_list ap;
+ char key[1024];
+ char val[1024];
+ int n;
+
+ if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ va_start(ap, fmt);
+ n = vsnprintf(val, sizeof(val), fmt, ap);
+ va_end(ap);
+ if (n >= sizeof(val)) {
+ errno = ENOSPC; /* close enough */
+ return -1;
+ }
+
+ if (!xs_write(xsh, XBT_NULL, key, val, n))
+ return -1;
+ return 0;
+}
+
+static void xenfb_device_init(struct xenfb_device *dev,
+ const char *type,
+ struct xenfb_private *xenfb)
+{
+ dev->devicetype = type;
+ dev->otherend_id = -1;
+ dev->port = -1;
+ dev->xenfb = xenfb;
+}
+
+int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
+{
+ struct xenfb_private *xenfb = dev->xenfb;
+
+ dev->otherend_id = domid;
+
+ if (!xenfb_path_in_dom(xenfb->xsh,
+ dev->otherend, sizeof(dev->otherend),
+ domid, "device/%s/0", dev->devicetype)) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (!xenfb_path_in_dom(xenfb->xsh,
+ dev->nodename, sizeof(dev->nodename),
+ 0, "backend/%s/%d/0", dev->devicetype, domid)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ return 0;
+}
+
+struct xenfb *xenfb_new(void)
+{
+ struct xenfb_private *xenfb = malloc(sizeof(*xenfb));
+ int serrno;
+
+ if (xenfb == NULL)
+ return NULL;
+
+ memset(xenfb, 0, sizeof(*xenfb));
+ xenfb->evt_xch = xenfb->xc = -1;
+ xenfb_device_init(&xenfb->fb, "vfb", xenfb);
+ xenfb_device_init(&xenfb->kbd, "vkbd", xenfb);
+
+ xenfb->evt_xch = xc_evtchn_open();
+ if (xenfb->evt_xch == -1)
+ goto fail;
+
+ xenfb->xc = xc_interface_open();
+ if (xenfb->xc == -1)
+ goto fail;
+
+ xenfb->xsh = xs_daemon_open();
+ if (!xenfb->xsh)
+ goto fail;
+
+ return &xenfb->pub;
+
+ fail:
+ serrno = errno;
+ xenfb_delete(&xenfb->pub);
+ errno = serrno;
+ return NULL;
+}
+
+/* Remove the backend area in xenbus since the framebuffer really is
+ going away. */
+void xenfb_teardown(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
+ xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
+}
+
+
+void xenfb_delete(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+
+ xenfb_detach_dom(xenfb);
+ if (xenfb->xc >= 0)
+ xc_interface_close(xenfb->xc);
+ if (xenfb->evt_xch >= 0)
+ xc_evtchn_close(xenfb->evt_xch);
+ if (xenfb->xsh)
+ xs_daemon_close(xenfb->xsh);
+ free(xenfb);
+}
+
+static enum xenbus_state xenfb_read_state(struct xs_handle *xsh,
+ const char *dir)
+{
+ int ret, state;
+
+ ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
+ if (ret < 0)
+ return XenbusStateUnknown;
+
+ if ((unsigned)state > XenbusStateClosed)
+ state = XenbusStateUnknown;
+ return state;
+}
+
+static int xenfb_switch_state(struct xenfb_device *dev,
+ enum xenbus_state state)
+{
+ struct xs_handle *xsh = dev->xenfb->xsh;
+
+ if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
+ return -1;
+ dev->state = state;
+ return 0;
+}
+
+static int xenfb_wait_for_state(struct xs_handle *xsh, const char *dir,
+ unsigned awaited)
+{
+ unsigned state, dummy;
+ char **vec;
+
+ awaited |= 1 << XenbusStateUnknown;
+
+ for (;;) {
+ state = xenfb_read_state(xsh, dir);
+ if ((1 << state) & awaited)
+ return state;
+
+ vec = xs_read_watch(xsh, &dummy);
+ if (!vec)
+ return -1;
+ free(vec);
+ }
+}
+
+static int xenfb_wait_for_backend_creation(struct xenfb_device *dev)
+{
+ struct xs_handle *xsh = dev->xenfb->xsh;
+ int state;
+
+ if (!xs_watch(xsh, dev->nodename, ""))
+ return -1;
+ state = xenfb_wait_for_state(xsh, dev->nodename,
+ (1 << XenbusStateInitialising)
+ | (1 << XenbusStateClosed)
+#if 1 /* TODO fudging state to permit restarting; to be removed */
+ | (1 << XenbusStateInitWait)
+ | (1 << XenbusStateConnected)
+ | (1 << XenbusStateClosing)
+#endif
+ );
+ xs_unwatch(xsh, dev->nodename, "");
+
+ switch (state) {
+#if 1
+ case XenbusStateInitWait:
+ case XenbusStateConnected:
+ printf("Fudging state to %d\n", XenbusStateInitialising); /* FIXME */
+#endif
+ case XenbusStateInitialising:
+ case XenbusStateClosing:
+ case XenbusStateClosed:
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static int xenfb_hotplug(struct xenfb_device *dev)
+{
+ if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename,
+ "hotplug-status", "connected"))
+ return -1;
+ return 0;
+}
+
+static int xenfb_wait_for_frontend_initialised(struct xenfb_device *dev)
+{
+ switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
+#if 1 /* TODO fudging state to permit restarting; to be removed */
+ (1 << XenbusStateInitialised)
+ | (1 << XenbusStateConnected)
+#else
+ 1 << XenbusStateInitialised,
+#endif
+ )) {
+#if 1
+ case XenbusStateConnected:
+ printf("Fudging state to %d\n", XenbusStateInitialised); /* FIXME */
+#endif
+ case XenbusStateInitialised:
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
+{
+ uint32_t *src32 = src;
+ uint64_t *src64 = src;
+ int i;
+
+ for (i = 0; i < count; i++)
+ dst[i] = (mode == 32) ? src32[i] : src64[i];
+}
+
+static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
+{
+ struct xenfb_page *page = xenfb->fb.page;
+ int n_fbmfns;
+ int n_fbdirs;
+ unsigned long *pgmfns = NULL;
+ unsigned long *fbmfns = NULL;
+ void *map, *pd;
+ int mode, ret = -1;
+
+ /* default to native */
+ pd = page->pd;
+ mode = sizeof(unsigned long) * 8;
+
+ if (0 == strlen(xenfb->protocol)) {
+ /*
+ * Undefined protocol, some guesswork needed.
+ *
+ * Old frontends which don't set the protocol use
+ * one page directory only, thus pd[1] must be zero.
+ * pd[1] of the 32bit struct layout and the lower
+ * 32 bits of pd[0] of the 64bit struct layout have
+ * the same location, so we can check that ...
+ */
+ uint32_t *ptr32 = NULL;
+ uint32_t *ptr64 = NULL;
+#if defined(__i386__)
+ ptr32 = (void*)page->pd;
+ ptr64 = ((void*)page->pd) + 4;
+#elif defined(__x86_64__)
+ ptr32 = ((void*)page->pd) - 4;
+ ptr64 = (void*)page->pd;
+#endif
+ if (ptr32) {
+ if (0 == ptr32[1]) {
+ mode = 32;
+ pd = ptr32;
+ } else {
+ mode = 64;
+ pd = ptr64;
+ }
+ }
+#if defined(__x86_64__)
+ } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
+ /* 64bit dom0, 32bit domU */
+ mode = 32;
+ pd = ((void*)page->pd) - 4;
+#elif defined(__i386__)
+ } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
+ /* 32bit dom0, 64bit domU */
+ mode = 64;
+ pd = ((void*)page->pd) + 4;
+#endif
+ }
+
+ n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+ n_fbdirs = n_fbmfns * mode / 8;
+ n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
+
+ pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
+ fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
+ if (!pgmfns || !fbmfns)
+ goto out;
+
+ /*
+ * Bug alert: xc_map_foreign_batch() can fail partly and
+ * return a non-null value. This is a design flaw. When it
+ * happens, we happily continue here, and later crash on
+ * access.
+ */
+ xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
+ map = xc_map_foreign_batch(xenfb->xc, domid,
+ PROT_READ, pgmfns, n_fbdirs);
+ if (map == NULL)
+ goto out;
+ xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
+ munmap(map, n_fbdirs * XC_PAGE_SIZE);
+
+ xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid,
+ PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
+ if (xenfb->pub.pixels == NULL)
+ goto out;
+
+ ret = 0; /* all is fine */
+
+ out:
+ if (pgmfns)
+ free(pgmfns);
+ if (fbmfns)
+ free(fbmfns);
+ return ret;
+}
+
+static int xenfb_bind(struct xenfb_device *dev)
+{
+ struct xenfb_private *xenfb = dev->xenfb;
+ unsigned long mfn;
+ evtchn_port_t evtchn;
+
+ if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "page-ref", "%lu",
+ &mfn) < 0)
+ return -1;
+ if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
+ &evtchn) < 0)
+ return -1;
+
+ dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
+ dev->otherend_id, evtchn);
+ if (dev->port == -1)
+ return -1;
+
+ dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
+ XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
+ if (dev->page == NULL)
+ return -1;
+
+ return 0;
+}
+
+static void xenfb_unbind(struct xenfb_device *dev)
+{
+ if (dev->page) {
+ munmap(dev->page, XC_PAGE_SIZE);
+ dev->page = NULL;
+ }
+ if (dev->port >= 0) {
+ xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port);
+ dev->port = -1;
+ }
+}
+
+static int xenfb_wait_for_frontend_connected(struct xenfb_device *dev)
+{
+ switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
+ 1 << XenbusStateConnected)) {
+ case XenbusStateConnected:
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static void xenfb_dev_fatal(struct xenfb_device *dev, int err,
+ const char *fmt, ...)
+{
+ struct xs_handle *xsh = dev->xenfb->xsh;
+ va_list ap;
+ char errdir[80];
+ char buf[1024];
+ int n;
+
+ fprintf(stderr, "%s ", dev->nodename); /* somewhat crude */
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (err)
+ fprintf(stderr, " (%s)", strerror(err));
+ putc('\n', stderr);
+
+ if (!xenfb_path_in_dom(xsh, errdir, sizeof(errdir), 0,
+ "error/%s", dev->nodename))
+ goto out; /* FIXME complain */
+
+ va_start(ap, fmt);
+ n = snprintf(buf, sizeof(buf), "%d ", err);
+ snprintf(buf + n, sizeof(buf) - n, fmt, ap);
+ va_end(ap);
+
+ if (xenfb_xs_printf(xsh, buf, "error", "%s", buf) < 0)
+ goto out; /* FIXME complain */
+
+ out:
+ xenfb_switch_state(dev, XenbusStateClosing);
+}
+
+int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ struct xs_handle *xsh = xenfb->xsh;
+ int val, serrno;
+ struct xenfb_page *fb_page;
+
+ xenfb_detach_dom(xenfb);
+
+ xenfb_device_set_domain(&xenfb->fb, domid);
+ xenfb_device_set_domain(&xenfb->kbd, domid);
+
+ if (xenfb_wait_for_backend_creation(&xenfb->fb) < 0)
+ goto error;
+ if (xenfb_wait_for_backend_creation(&xenfb->kbd) < 0)
+ goto error;
+
+ if (xenfb_xs_printf(xsh, xenfb->kbd.nodename, "feature-abs-pointer", "1"))
+ goto error;
+ if (xenfb_switch_state(&xenfb->fb, XenbusStateInitWait))
+ goto error;
+ if (xenfb_switch_state(&xenfb->kbd, XenbusStateInitWait))
+ goto error;
+
+ if (xenfb_hotplug(&xenfb->fb) < 0)
+ goto error;
+ if (xenfb_hotplug(&xenfb->kbd) < 0)
+ goto error;
+
+ if (!xs_watch(xsh, xenfb->fb.otherend, ""))
+ goto error;
+ if (!xs_watch(xsh, xenfb->kbd.otherend, ""))
+ goto error;
+
+ if (xenfb_wait_for_frontend_initialised(&xenfb->fb) < 0)
+ goto error;
+ if (xenfb_wait_for_frontend_initialised(&xenfb->kbd) < 0)
+ goto error;
+
+ if (xenfb_bind(&xenfb->fb) < 0)
+ goto error;
+ if (xenfb_bind(&xenfb->kbd) < 0)
+ goto error;
+
+ if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "feature-update",
+ "%d", &val) < 0)
+ val = 0;
+ if (!val) {
+ errno = ENOTSUP;
+ goto error;
+ }
+ if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "protocol", "%63s",
+ xenfb->protocol) < 0)
+ xenfb->protocol[0] = '\0';
+ xenfb_xs_printf(xsh, xenfb->fb.nodename, "request-update", "1");
+
+ /* TODO check for permitted ranges */
+ fb_page = xenfb->fb.page;
+ xenfb->pub.depth = fb_page->depth;
+ xenfb->pub.width = fb_page->width;
+ xenfb->pub.height = fb_page->height;
+ /* TODO check for consistency with the above */
+ xenfb->fb_len = fb_page->mem_length;
+ xenfb->pub.row_stride = fb_page->line_length;
+
+ if (xenfb_map_fb(xenfb, domid) < 0)
+ goto error;
+
+ if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected))
+ goto error;
+ if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected))
+ goto error;
+
+ if (xenfb_wait_for_frontend_connected(&xenfb->kbd) < 0)
+ goto error;
+ if (xenfb_xs_scanf1(xsh, xenfb->kbd.otherend, "request-abs-pointer",
+ "%d", &val) < 0)
+ val = 0;
+ xenfb->pub.abs_pointer_wanted = val;
+
+ return 0;
+
+ error:
+ serrno = errno;
+ xenfb_detach_dom(xenfb);
+ xenfb_dev_fatal(&xenfb->fb, serrno, "on fire");
+ xenfb_dev_fatal(&xenfb->kbd, serrno, "on fire");
+ errno = serrno;
+ return -1;
+}
+
+static void xenfb_detach_dom(struct xenfb_private *xenfb)
+{
+ xenfb_unbind(&xenfb->fb);
+ xenfb_unbind(&xenfb->kbd);
+ if (xenfb->pub.pixels) {
+ munmap(xenfb->pub.pixels, xenfb->fb_len);
+ xenfb->pub.pixels = NULL;
+ }
+}
+
+static void xenfb_on_fb_event(struct xenfb_private *xenfb)
+{
+ uint32_t prod, cons;
+ struct xenfb_page *page = xenfb->fb.page;
+
+ prod = page->out_prod;
+ if (prod == page->out_cons)
+ return;
+ rmb(); /* ensure we see ring contents up to prod */
+ for (cons = page->out_cons; cons != prod; cons++) {
+ union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
+
+ switch (event->type) {
+ case XENFB_TYPE_UPDATE:
+ if (xenfb->pub.update)
+ xenfb->pub.update(&xenfb->pub,
+ event->update.x, event->update.y,
+ event->update.width, event->update.height);
+ break;
+ }
+ }
+ mb(); /* ensure we're done with ring contents */
+ page->out_cons = cons;
+ xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
+}
+
+static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
+{
+ struct xenkbd_page *page = xenfb->kbd.page;
+
+ /* We don't understand any keyboard events, so just ignore them. */
+ if (page->out_prod == page->out_cons)
+ return;
+ page->out_cons = page->out_prod;
+ xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
+}
+
+static int xenfb_on_state_change(struct xenfb_device *dev)
+{
+ enum xenbus_state state;
+
+ state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
+
+ switch (state) {
+ case XenbusStateUnknown:
+ /* There was an error reading the frontend state. The
+ domain has probably gone away; in any case, there's
+ not much point in us continuing. */
+ return -1;
+ case XenbusStateInitialising:
+ case XenbusStateInitWait:
+ case XenbusStateInitialised:
+ case XenbusStateConnected:
+ break;
+ case XenbusStateClosing:
+ xenfb_unbind(dev);
+ xenfb_switch_state(dev, state);
+ break;
+ case XenbusStateClosed:
+ xenfb_switch_state(dev, state);
+ }
+ return 0;
+}
+
+int xenfb_dispatch_channel(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ evtchn_port_t port;
+ port = xc_evtchn_pending(xenfb->evt_xch);
+ if (port == -1)
+ return -1;
+
+ if (port == xenfb->fb.port)
+ xenfb_on_fb_event(xenfb);
+ else if (port == xenfb->kbd.port)
+ xenfb_on_kbd_event(xenfb);
+
+ if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
+ return -1;
+
+ return 0;
+}
+
+int xenfb_dispatch_store(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ unsigned dummy;
+ char **vec;
+ int r;
+
+ vec = xs_read_watch(xenfb->xsh, &dummy);
+ free(vec);
+ r = xenfb_on_state_change(&xenfb->fb);
+ if (r == 0)
+ r = xenfb_on_state_change(&xenfb->kbd);
+ if (r == -1)
+ return -2;
+
+ return 0;
+}
+
+
+/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
+int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ int ret;
+
+ if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
+ if ((ret = xenfb_dispatch_channel(xenfb_pub)) < 0)
+ return ret;
+ }
+
+ if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
+ if ((ret = xenfb_dispatch_store(xenfb_pub)) < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+int xenfb_select_fds(struct xenfb *xenfb_pub, fd_set *readfds)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ int fd1 = xc_evtchn_fd(xenfb->evt_xch);
+ int fd2 = xs_fileno(xenfb->xsh);
+
+ FD_SET(fd1, readfds);
+ FD_SET(fd2, readfds);
+ return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
+}
+
+int xenfb_get_store_fd(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ return xs_fileno(xenfb->xsh);
+}
+
+int xenfb_get_channel_fd(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ return xc_evtchn_fd(xenfb->evt_xch);
+}
+
+static int xenfb_kbd_event(struct xenfb_private *xenfb,
+ union xenkbd_in_event *event)
+{
+ uint32_t prod;
+ struct xenkbd_page *page = xenfb->kbd.page;
+
+ if (xenfb->kbd.state != XenbusStateConnected)
+ return 0;
+
+ prod = page->in_prod;
+ if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ mb(); /* ensure ring space available */
+ XENKBD_IN_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->in_prod = prod + 1;
+ return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
+}
+
+int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_KEY;
+ event.key.pressed = down ? 1 : 0;
+ event.key.keycode = keycode;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+
+int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_MOTION;
+ event.motion.rel_x = rel_x;
+ event.motion.rel_y = rel_y;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+
+int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ union xenkbd_in_event event;
+
+ memset(&event, 0, XENKBD_IN_EVENT_SIZE);
+ event.type = XENKBD_TYPE_POS;
+ event.pos.abs_x = abs_x;
+ event.pos.abs_y = abs_y;
+
+ return xenfb_kbd_event(xenfb, &event);
+}
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -rupN xen-3.1.0-src.orig/tools/ioemu/hw/xenfb.h xen-3.1.0-src.new/tools/ioemu/hw/xenfb.h
--- xen-3.1.0-src.orig/tools/ioemu/hw/xenfb.h 1969-12-31 19:00:00.000000000 -0500
+++ xen-3.1.0-src.new/tools/ioemu/hw/xenfb.h 2007-08-23 11:05:47.000000000 -0400
@@ -0,0 +1,39 @@
+#ifndef _XENFB_H_
+#define _XENFB_H_
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+struct xenfb
+{
+ void *pixels;
+
+ int row_stride;
+ int depth;
+ int width;
+ int height;
+ int abs_pointer_wanted;
+
+ void *user_data;
+
+ void (*update)(struct xenfb *xenfb, int x, int y, int width, int height);
+};
+
+struct xenfb *xenfb_new(void);
+void xenfb_delete(struct xenfb *xenfb);
+void xenfb_teardown(struct xenfb *xenfb);
+
+int xenfb_attach_dom(struct xenfb *xenfb, int domid);
+
+int xenfb_dispatch_store(struct xenfb *xenfb_pub);
+int xenfb_dispatch_channel(struct xenfb *xenfb_pub);
+int xenfb_select_fds(struct xenfb *xenfb, fd_set *readfds);
+int xenfb_poll(struct xenfb *xenfb, fd_set *readfds);
+int xenfb_get_store_fd(struct xenfb *xenfb_pub);
+int xenfb_get_channel_fd(struct xenfb *xenfb_pub);
+
+int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
+int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
+int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);
+
+#endif
diff -rupN xen-3.1.0-src.orig/tools/ioemu/hw/xen_machine_pv.c xen-3.1.0-src.new/tools/ioemu/hw/xen_machine_pv.c
--- xen-3.1.0-src.orig/tools/ioemu/hw/xen_machine_pv.c 2007-08-23 11:05:27.000000000 -0400
+++ xen-3.1.0-src.new/tools/ioemu/hw/xen_machine_pv.c 2007-08-23 11:05:47.000000000 -0400
@@ -23,7 +23,7 @@
*/
#include "vl.h"
-#include "../../xenfb/xenfb.h"
+#include "xenfb.h"
#include <linux/input.h>
/* A convenient function for munging pixels between different depths */
diff -rupN xen-3.1.0-src.orig/tools/ioemu/Makefile.target xen-3.1.0-src.new/tools/ioemu/Makefile.target
--- xen-3.1.0-src.orig/tools/ioemu/Makefile.target 2007-08-23 11:05:27.000000000 -0400
+++ xen-3.1.0-src.new/tools/ioemu/Makefile.target 2007-08-23 11:05:47.000000000 -0400
@@ -371,7 +371,7 @@ VL_OBJS+= xenstore.o
VL_OBJS+= xen_platform.o
VL_OBJS+= xen_machine_fv.o
VL_OBJS+= xen_machine_pv.o
-VL_OBJS+= ../../xenfb/xenfb.o
+VL_OBJS+= xenfb.o
VL_OBJS+= tpm_tis.o
DEFINES += -DHAS_AUDIO
endif
diff -rupN xen-3.1.0-src.orig/tools/Makefile xen-3.1.0-src.new/tools/Makefile
--- xen-3.1.0-src.orig/tools/Makefile 2007-08-23 11:05:27.000000000 -0400
+++ xen-3.1.0-src.new/tools/Makefile 2007-08-23 11:05:41.000000000 -0400
@@ -19,7 +19,6 @@ SUBDIRS-y += xenstat
SUBDIRS-y += libaio
SUBDIRS-y += blktap
SUBDIRS-y += libfsimage
-SUBDIRS-$(XENFB_TOOLS) += xenfb
SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
# These don't cross-compile
diff -rupN xen-3.1.0-src.orig/tools/xenfb/Makefile xen-3.1.0-src.new/tools/xenfb/Makefile
--- xen-3.1.0-src.orig/tools/xenfb/Makefile 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/xenfb/Makefile 1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-XEN_ROOT=../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-CFLAGS += -I$(XEN_LIBXC) -I$(XEN_XENSTORE)
-CFLAGS += -I$(XEN_ROOT)/linux-2.6-xen-sparse/include -I$(XEN_ROOT)/tools/ioemu
-LDFLAGS += -L$(XEN_LIBXC) -L$(XEN_XENSTORE)
-
-.PHONY: all
-all: build
-
-.PHONY: build
-build:
- $(MAKE) vncfb sdlfb
-
-install: all
- $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)/xen/bin
- $(INSTALL_PROG) vncfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-vncfb
- $(INSTALL_PROG) sdlfb $(DESTDIR)/usr/$(LIBDIR)/xen/bin/xen-sdlfb
-
-sdlfb: sdlfb.o xenfb.o
-
-sdlfb.o: CFLAGS += $(shell sdl-config --cflags)
-sdlfb: LDLIBS += $(shell sdl-config --libs) -lxenctrl -lxenstore
-
-clean:
- $(RM) *.o *~ vncfb sdlfb
-
-vncfb: vncfb.o xenfb.o
-vncfb.o: CFLAGS += $(shell libvncserver-config --cflags)
-vncfb: LDLIBS += $(shell libvncserver-config --libs) -lxenctrl -lxenstore
-
-sdlfb.o xenfb.o vncfb.o: xenfb.h
diff -rupN xen-3.1.0-src.orig/tools/xenfb/sdlfb.c xen-3.1.0-src.new/tools/xenfb/sdlfb.c
--- xen-3.1.0-src.orig/tools/xenfb/sdlfb.c 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/xenfb/sdlfb.c 1969-12-31 19:00:00.000000000 -0500
@@ -1,342 +0,0 @@
-#include <SDL.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/select.h>
-#include <stdlib.h>
-#include <linux/input.h>
-#include <getopt.h>
-#include <string.h>
-#include "xenfb.h"
-
-struct SDLFBData
-{
- SDL_Surface *dst;
- SDL_Surface *src;
-};
-
-/*
- * Map from scancode to Linux input layer keycode. Scancodes are
- * hardware-specific. This map assumes a standard AT or PS/2
- * keyboard.
- *
- * Why use scancodes? We can't use key symbols, because they don't
- * identify keys --- they're what keys are mapped to. The standard
- * German keymap, for instance, maps both KEY_COMMA and KEY_102ND to
- * SDLK_LESS.
- */
-static int keymap[256] = {
- [9] = KEY_ESC,
- [10] = KEY_1,
- [11] = KEY_2,
- [12] = KEY_3,
- [13] = KEY_4,
- [14] = KEY_5,
- [15] = KEY_6,
- [16] = KEY_7,
- [17] = KEY_8,
- [18] = KEY_9,
- [19] = KEY_0,
- [20] = KEY_MINUS,
- [21] = KEY_EQUAL,
- [22] = KEY_BACKSPACE,
- [23] = KEY_TAB,
- [24] = KEY_Q,
- [25] = KEY_W,
- [26] = KEY_E,
- [27] = KEY_R,
- [28] = KEY_T,
- [29] = KEY_Y,
- [30] = KEY_U,
- [31] = KEY_I,
- [32] = KEY_O,
- [33] = KEY_P,
- [34] = KEY_LEFTBRACE,
- [35] = KEY_RIGHTBRACE,
- [36] = KEY_ENTER,
- [37] = KEY_LEFTCTRL,
- [38] = KEY_A,
- [39] = KEY_S,
- [40] = KEY_D,
- [41] = KEY_F,
- [42] = KEY_G,
- [43] = KEY_H,
- [44] = KEY_J,
- [45] = KEY_K,
- [46] = KEY_L,
- [47] = KEY_SEMICOLON,
- [48] = KEY_APOSTROPHE,
- [49] = KEY_GRAVE,
- [50] = KEY_LEFTSHIFT,
- [51] = KEY_BACKSLASH,
- [52] = KEY_Z,
- [53] = KEY_X,
- [54] = KEY_C,
- [55] = KEY_V,
- [56] = KEY_B,
- [57] = KEY_N,
- [58] = KEY_M,
- [59] = KEY_COMMA,
- [60] = KEY_DOT,
- [61] = KEY_SLASH,
- [62] = KEY_RIGHTSHIFT,
- [63] = KEY_KPASTERISK,
- [64] = KEY_LEFTALT,
- [65] = KEY_SPACE,
- [66] = KEY_CAPSLOCK,
- [67] = KEY_F1,
- [68] = KEY_F2,
- [69] = KEY_F3,
- [70] = KEY_F4,
- [71] = KEY_F5,
- [72] = KEY_F6,
- [73] = KEY_F7,
- [74] = KEY_F8,
- [75] = KEY_F9,
- [76] = KEY_F10,
- [77] = KEY_NUMLOCK,
- [78] = KEY_SCROLLLOCK,
- [79] = KEY_KP7,
- [80] = KEY_KP8,
- [81] = KEY_KP9,
- [82] = KEY_KPMINUS,
- [83] = KEY_KP4,
- [84] = KEY_KP5,
- [85] = KEY_KP6,
- [86] = KEY_KPPLUS,
- [87] = KEY_KP1,
- [88] = KEY_KP2,
- [89] = KEY_KP3,
- [90] = KEY_KP0,
- [91] = KEY_KPDOT,
- [94] = KEY_102ND, /* FIXME is this correct? */
- [95] = KEY_F11,
- [96] = KEY_F12,
- [108] = KEY_KPENTER,
- [109] = KEY_RIGHTCTRL,
- [112] = KEY_KPSLASH,
- [111] = KEY_SYSRQ,
- [113] = KEY_RIGHTALT,
- [97] = KEY_HOME,
- [98] = KEY_UP,
- [99] = KEY_PAGEUP,
- [100] = KEY_LEFT,
- [102] = KEY_RIGHT,
- [103] = KEY_END,
- [104] = KEY_DOWN,
- [105] = KEY_PAGEDOWN,
- [106] = KEY_INSERT,
- [107] = KEY_DELETE,
- [110] = KEY_PAUSE,
- [115] = KEY_LEFTMETA,
- [116] = KEY_RIGHTMETA,
- [117] = KEY_MENU,
-};
-
-static int btnmap[] = {
- [SDL_BUTTON_LEFT] = BTN_LEFT,
- [SDL_BUTTON_MIDDLE] = BTN_MIDDLE,
- [SDL_BUTTON_RIGHT] = BTN_RIGHT,
- /* FIXME not 100% sure about these: */
- [SDL_BUTTON_WHEELUP] = BTN_FORWARD,
- [SDL_BUTTON_WHEELDOWN] BTN_BACK
-};
-
-static void sdl_update(struct xenfb *xenfb, int x, int y, int width, int height)
-{
- struct SDLFBData *data = xenfb->user_data;
- SDL_Rect r = { x, y, width, height };
- SDL_BlitSurface(data->src, &r, data->dst, &r);
- SDL_UpdateRect(data->dst, x, y, width, height);
-}
-
-static int sdl_on_event(struct xenfb *xenfb, SDL_Event *event)
-{
- int x, y, ret;
-
- switch (event->type) {
- case SDL_KEYDOWN:
- case SDL_KEYUP:
- if (keymap[event->key.keysym.scancode] == 0)
- break;
- ret = xenfb_send_key(xenfb,
- event->type == SDL_KEYDOWN,
- keymap[event->key.keysym.scancode]);
- if (ret < 0)
- fprintf(stderr, "Key %d %s lost (%s)\n",
- keymap[event->key.keysym.scancode],
- event->type == SDL_KEYDOWN ? "down" : "up",
- strerror(errno));
- break;
- case SDL_MOUSEMOTION:
- if (xenfb->abs_pointer_wanted) {
- SDL_GetMouseState(&x, &y);
- ret = xenfb_send_position(xenfb, x, y);
- } else {
- SDL_GetRelativeMouseState(&x, &y);
- ret = xenfb_send_motion(xenfb, x, y);
- }
- if (ret < 0)
- fprintf(stderr, "Pointer to %d,%d lost (%s)\n",
- x, y, strerror(errno));
- break;
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- if (event->button.button >= sizeof(btnmap) / sizeof(*btnmap))
- break;
- if (btnmap[event->button.button] == 0)
- break;
- ret = xenfb_send_key(xenfb,
- event->type == SDL_MOUSEBUTTONDOWN,
- btnmap[event->button.button]);
- if (ret < 0)
- fprintf(stderr, "Button %d %s lost (%s)\n",
- btnmap[event->button.button] - BTN_MOUSE,
- event->type == SDL_MOUSEBUTTONDOWN ? "down" : "up",
- strerror(errno));
- break;
- case SDL_QUIT:
- return 0;
- }
-
- return 1;
-}
-
-static struct option options[] = {
- { "domid", 1, NULL, 'd' },
- { "title", 1, NULL, 't' },
- { NULL }
-};
-
-int main(int argc, char **argv)
-{
- struct xenfb *xenfb;
- int domid = -1;
- char * title = NULL;
- fd_set readfds;
- int nfds;
- struct SDLFBData data;
- SDL_Rect r;
- struct timeval tv;
- SDL_Event event;
- int do_quit = 0;
- int opt;
- char *endp;
- int retval;
-
- while ((opt = getopt_long(argc, argv, "d:t:", options,
- NULL)) != -1) {
- switch (opt) {
- case 'd':
- domid = strtol(optarg, &endp, 10);
- if (endp == optarg || *endp) {
- fprintf(stderr, "Invalid domain id specified\n");
- exit(1);
- }
- break;
- case 't':
- title = strdup(optarg);
- break;
- case '?':
- exit(1);
- }
- }
- if (optind != argc) {
- fprintf(stderr, "Invalid options!\n");
- exit(1);
- }
- if (domid <= 0) {
- fprintf(stderr, "Domain ID must be specified!\n");
- exit(1);
- }
-
- xenfb = xenfb_new();
- if (xenfb == NULL) {
- fprintf(stderr, "Could not create framebuffer (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- if (xenfb_attach_dom(xenfb, domid) < 0) {
- fprintf(stderr, "Could not connect to domain (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- if (SDL_Init(SDL_INIT_VIDEO) < 0) {
- fprintf(stderr, "Could not initialize SDL\n");
- exit(1);
- }
-
- data.dst = SDL_SetVideoMode(xenfb->width, xenfb->height, xenfb->depth,
- SDL_SWSURFACE);
- if (!data.dst) {
- fprintf(stderr, "SDL_SetVideoMode failed\n");
- exit(1);
- }
-
- data.src = SDL_CreateRGBSurfaceFrom(xenfb->pixels,
- xenfb->width, xenfb->height,
- xenfb->depth, xenfb->row_stride,
- 0xFF0000, 0xFF00, 0xFF, 0);
-
- if (!data.src) {
- fprintf(stderr, "SDL_CreateRGBSurfaceFrom failed\n");
- exit(1);
- }
-
- if (title == NULL)
- title = strdup("xen-sdlfb");
- SDL_WM_SetCaption(title, title);
-
- r.x = r.y = 0;
- r.w = xenfb->width;
- r.h = xenfb->height;
- SDL_BlitSurface(data.src, &r, data.dst, &r);
- SDL_UpdateRect(data.dst, 0, 0, xenfb->width, xenfb->height);
-
- xenfb->update = sdl_update;
- xenfb->user_data = &data;
-
- SDL_ShowCursor(0);
-
- /*
- * We need to wait for fds becoming ready or SDL events to
- * arrive. We time out the select after 10ms to poll for SDL
- * events. Clunky, but works. Could avoid the clunkiness
- * with a separate thread.
- */
- for (;;) {
- FD_ZERO(&readfds);
- nfds = xenfb_select_fds(xenfb, &readfds);
- tv = (struct timeval){0, 10000};
-
- if (select(nfds, &readfds, NULL, NULL, &tv) < 0) {
- if (errno == EINTR)
- continue;
- fprintf(stderr,
- "Can't select() on event channel (%s)\n",
- strerror(errno));
- break;
- }
-
- while (SDL_PollEvent(&event)) {
- if (!sdl_on_event(xenfb, &event))
- do_quit = 1;
- }
-
- if (do_quit)
- break;
-
- retval = xenfb_poll(xenfb, &readfds);
- if (retval == -2)
- xenfb_teardown(xenfb);
- if (retval < 0)
- break;
- }
-
- xenfb_delete(xenfb);
-
- SDL_Quit();
-
- return 0;
-}
diff -rupN xen-3.1.0-src.orig/tools/xenfb/vncfb.c xen-3.1.0-src.new/tools/xenfb/vncfb.c
--- xen-3.1.0-src.orig/tools/xenfb/vncfb.c 2007-05-18 10:45:21.000000000 -0400
+++ xen-3.1.0-src.new/tools/xenfb/vncfb.c 1969-12-31 19:00:00.000000000 -0500
@@ -1,422 +0,0 @@
-#define _GNU_SOURCE
-#include <errno.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <rfb/rfb.h>
-#include <rfb/keysym.h>
-#include <linux/input.h>
-#include <xs.h>
-#include "xenfb.h"
-
-/* Grab key translation support routines from qemu directory. */
-#define qemu_mallocz(size) calloc(1, (size))
-static const char *bios_dir = "/usr/share/xen/qemu";
-#include "vnc_keysym.h"
-#include "keymaps.c"
-
-static unsigned char atkbd_set2_keycode[512] = {
-
- 0, 67, 65, 63, 61, 59, 60, 88, 0, 68, 66, 64, 62, 15, 41,117,
- 0, 56, 42, 93, 29, 16, 2, 0, 0, 0, 44, 31, 30, 17, 3, 0,
- 0, 46, 45, 32, 18, 5, 4, 95, 0, 57, 47, 33, 20, 19, 6,183,
- 0, 49, 48, 35, 34, 21, 7,184, 0, 0, 50, 36, 22, 8, 9,185,
- 0, 51, 37, 23, 24, 11, 10, 0, 0, 52, 53, 38, 39, 25, 12, 0,
- 0, 89, 40, 0, 26, 13, 0, 0, 58, 54, 28, 27, 0, 43, 0, 85,
- 0, 86, 91, 90, 92, 0, 14, 94, 0, 79,124, 75, 71,121, 0, 0,
- 82, 83, 80, 76, 77, 72, 1, 69, 87, 78, 81, 74, 55, 73, 70, 99,
-
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 217,100,255, 0, 97,165, 0, 0,156, 0, 0, 0, 0, 0, 0,125,
- 173,114, 0,113, 0, 0, 0,126,128, 0, 0,140, 0, 0, 0,127,
- 159, 0,115, 0,164, 0, 0,116,158, 0,150,166, 0, 0, 0,142,
- 157, 0, 0, 0, 0, 0, 0, 0,155, 0, 98, 0, 0,163, 0, 0,
- 226, 0, 0, 0, 0, 0, 0, 0, 0,255, 96, 0, 0, 0,143, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0,105,102, 0, 0,112,
- 110,111,108,112,106,103, 0,119, 0,118,109, 0, 99,104,119, 0,
-
-};
-
-static unsigned char atkbd_unxlate_table[128] = {
-
- 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13,
- 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27,
- 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42,
- 50, 49, 58, 65, 73, 74, 89,124, 17, 41, 88, 5, 6, 4, 12, 3,
- 11, 2, 10, 1, 9,119,126,108,117,125,123,107,115,116,121,105,
- 114,122,112,113,127, 96, 97,120, 7, 15, 23, 31, 39, 47, 55, 63,
- 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87,111,
- 19, 25, 57, 81, 83, 92, 95, 98, 99,100,101,103,104,106,109,110
-
-};
-
-unsigned char keycode_table[512];
-
-static void *kbd_layout;
-
-static int btnmap[] = {
- BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE,
- BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK
-};
-
-static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl)
-{
- /*
- * We need to map to the key's Linux input layer keycode.
- * Unfortunately, we don't get the key here, only the
- * rfbKeySym, which is what the key is mapped to. Mapping
- * back to the key is impossible in general, even when you
- * know the keymap. For instance, the standard German keymap
- * maps both KEY_COMMA and KEY_102ND to XK_less. We simply
- * assume standard US layout. This sucks.
- */
- rfbScreenInfoPtr server = cl->screen;
- struct xenfb *xenfb = server->screenData;
- int scancode;
-
- if (keycode >= 'A' && keycode <= 'Z')
- keycode += 'a' - 'A';
-
- scancode = keycode_table[keysym2scancode(kbd_layout, keycode)];
- if (scancode == 0)
- return;
- if (xenfb_send_key(xenfb, down, scancode) < 0)
- fprintf(stderr, "Key %d %s lost (%s)\n",
- scancode, down ? "down" : "up",
- strerror(errno));
-}
-
-static void on_ptr_event(int buttonMask, int x, int y, rfbClientPtr cl)
-{
- /* initial pointer state: at (0,0), buttons up */
- static int last_x, last_y, last_button;
- rfbScreenInfoPtr server = cl->screen;
- struct xenfb *xenfb = server->screenData;
- int i, last_down, down, ret;
-
- for (i = 0; i < 8; i++) {
- last_down = last_button & (1 << i);
- down = buttonMask & (1 << i);
- if (down == last_down)
- continue;
- if (i >= sizeof(btnmap) / sizeof(*btnmap))
- break;
- if (btnmap[i] == 0)
- break;
- if (xenfb_send_key(xenfb, down != 0, btnmap[i]) < 0)
- fprintf(stderr, "Button %d %s lost (%s)\n",
- i, down ? "down" : "up", strerror(errno));
- }
-
- if (x != last_x || y != last_y) {
- if (xenfb->abs_pointer_wanted)
- ret = xenfb_send_position(xenfb, x, y);
- else
- ret = xenfb_send_motion(xenfb, x - last_x, y - last_y);
- if (ret < 0)
- fprintf(stderr, "Pointer to %d,%d lost (%s)\n",
- x, y, strerror(errno));
- }
-
- last_button = buttonMask;
- last_x = x;
- last_y = y;
-}
-
-static void xenstore_write_vncport(struct xs_handle *xsh, int port, int domid)
-{
- char *buf, *path;
- char portstr[10];
-
- path = xs_get_domain_path(xsh, domid);
- if (path == NULL) {
- fprintf(stderr, "Can't get domain path (%s)\n",
- strerror(errno));
- goto out;
- }
-
- if (asprintf(&buf, "%s/console/vnc-port", path) == -1) {
- fprintf(stderr, "Can't make vncport path\n");
- goto out;
- }
-
- if (snprintf(portstr, sizeof(portstr), "%d", port) == -1) {
- fprintf(stderr, "Can't make vncport value\n");
- goto out;
- }
-
- if (!xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)))
- fprintf(stderr, "Can't set vncport (%s)\n",
- strerror(errno));
-
- out:
- free(buf);
-}
-
-
-static int xenstore_read_vncpasswd(struct xs_handle *xsh, int domid, char *pwbuf, int pwbuflen)
-{
- char buf[256], *path, *uuid = NULL, *passwd = NULL;
- unsigned int len, rc = 0;
-
- if (xsh == NULL) {
- return -1;
- }
-
- path = xs_get_domain_path(xsh, domid);
- if (path == NULL) {
- fprintf(stderr, "xs_get_domain_path() error\n");
- return -1;
- }
-
- snprintf(buf, 256, "%s/vm", path);
- uuid = xs_read(xsh, XBT_NULL, buf, &len);
- if (uuid == NULL) {
- fprintf(stderr, "xs_read(): uuid get error\n");
- free(path);
- return -1;
- }
-
- snprintf(buf, 256, "%s/vncpasswd", uuid);
- passwd = xs_read(xsh, XBT_NULL, buf, &len);
- if (passwd == NULL) {
- free(uuid);
- free(path);
- return rc;
- }
-
- strncpy(pwbuf, passwd, pwbuflen-1);
- pwbuf[pwbuflen-1] = '\0';
-
- fprintf(stderr, "Got a VNC password read from XenStore\n");
-
- passwd[0] = '\0';
- snprintf(buf, 256, "%s/vncpasswd", uuid);
- if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
- fprintf(stderr, "xs_write() vncpasswd failed\n");
- rc = -1;
- }
-
- free(passwd);
- free(uuid);
- free(path);
-
- return rc;
-}
-
-static void vnc_update(struct xenfb *xenfb, int x, int y, int w, int h)
-{
- rfbScreenInfoPtr server = xenfb->user_data;
- rfbMarkRectAsModified(server, x, y, x + w, y + h);
-}
-
-static struct option options[] = {
- { "domid", 1, NULL, 'd' },
- { "vncport", 1, NULL, 'p' },
- { "title", 1, NULL, 't' },
- { "unused", 0, NULL, 'u' },
- { "listen", 1, NULL, 'l' },
- { "keymap", 1, NULL, 'k' },
- { NULL }
-};
-
-int main(int argc, char **argv)
-{
- rfbScreenInfoPtr server;
- char *fake_argv[7] = { "vncfb", "-rfbport", "5901",
- "-desktop", "xen-vncfb",
- "-listen", "127.0.0.1" };
- int fake_argc = sizeof(fake_argv) / sizeof(fake_argv[0]);
- int domid = -1, port = -1;
- char *title = NULL;
- char *listen = NULL;
- char *keymap = NULL;
- bool unused = false;
- int opt;
- struct xenfb *xenfb;
- fd_set readfds;
- int nfds;
- char portstr[10];
- char *endp;
- int r;
- struct xs_handle *xsh;
- char vncpasswd[1024];
- int i;
-
- vncpasswd[0] = '\0';
-
- while ((opt = getopt_long(argc, argv, "d:p:t:uk:", options,
- NULL)) != -1) {
- switch (opt) {
- case 'd':
- errno = 0;
- domid = strtol(optarg, &endp, 10);
- if (endp == optarg || *endp || errno) {
- fprintf(stderr, "Invalid domain id specified\n");
- exit(1);
- }
- break;
- case 'p':
- errno = 0;
- port = strtol(optarg, &endp, 10);
- if (endp == optarg || *endp || errno) {
- fprintf(stderr, "Invalid port specified\n");
- exit(1);
- }
- break;
- case 't':
- title = strdup(optarg);
- break;
- case 'u':
- unused = true;
- break;
- case 'l':
- listen = strdup(optarg);
- break;
- case 'k':
- keymap = strdup(optarg);
- break;
- case '?':
- exit(1);
- }
- }
- if (optind != argc) {
- fprintf(stderr, "Invalid options!\n");
- exit(1);
- }
- if (domid <= 0) {
- fprintf(stderr, "Domain ID must be specified!\n");
- exit(1);
- }
-
- if (port <= 0)
- port = 5900 + domid;
- if (snprintf(portstr, sizeof(portstr), "%d", port) == -1) {
- fprintf(stderr, "Invalid port specified\n");
- exit(1);
- }
-
- if (keymap == NULL){
- keymap = "en-us";
- }
-
- kbd_layout = init_keyboard_layout(keymap);
- if( !kbd_layout ){
- fprintf(stderr, "Invalid keyboard_layout\n");
- exit(1);
- }
-
- for (i = 0; i < 128; i++) {
- keycode_table[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
- keycode_table[i | 0x80] =
- atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
- }
-
- fake_argv[2] = portstr;
-
- if (title != NULL)
- fake_argv[4] = title;
-
- if (listen != NULL)
- fake_argv[6] = listen;
-
- signal(SIGPIPE, SIG_IGN);
-
- xenfb = xenfb_new();
- if (xenfb == NULL) {
- fprintf(stderr, "Could not create framebuffer (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- if (xenfb_attach_dom(xenfb, domid) < 0) {
- fprintf(stderr, "Could not connect to domain (%s)\n",
- strerror(errno));
- exit(1);
- }
-
- xsh = xs_daemon_open();
- if (xsh == NULL) {
- fprintf(stderr, "cannot open connection to xenstore\n");
- exit(1);
- }
-
-
- if (xenstore_read_vncpasswd(xsh, domid, vncpasswd,
- sizeof(vncpasswd)/sizeof(char)) < 0) {
- fprintf(stderr, "cannot read VNC password from xenstore\n");
- exit(1);
- }
-
-
- server = rfbGetScreen(&fake_argc, fake_argv,
- xenfb->width, xenfb->height,
- 8, 3, xenfb->depth / 8);
- if (server == NULL) {
- fprintf(stderr, "Could not create VNC server\n");
- exit(1);
- }
-
- xenfb->user_data = server;
- xenfb->update = vnc_update;
-
- if (unused)
- server->autoPort = true;
-
- if (vncpasswd[0]) {
- char **passwds = malloc(sizeof(char**)*2);
- if (!passwds) {
- fprintf(stderr, "cannot allocate memory (%s)\n",
- strerror(errno));
- exit(1);
- }
- fprintf(stderr, "Registered password\n");
- passwds[0] = vncpasswd;
- passwds[1] = NULL;
-
- server->authPasswdData = passwds;
- server->passwordCheck = rfbCheckPasswordByList;
- } else {
- fprintf(stderr, "Running with no password\n");
- }
- server->serverFormat.redShift = 16;
- server->serverFormat.greenShift = 8;
- server->serverFormat.blueShift = 0;
- server->kbdAddEvent = on_kbd_event;
- server->ptrAddEvent = on_ptr_event;
- server->frameBuffer = xenfb->pixels;
- server->screenData = xenfb;
- server->cursor = NULL;
- rfbInitServer(server);
-
- rfbRunEventLoop(server, -1, true);
-
- xenstore_write_vncport(xsh, server->port, domid);
-
- for (;;) {
- FD_ZERO(&readfds);
- nfds = xenfb_select_fds(xenfb, &readfds);
-
- if (select(nfds, &readfds, NULL, NULL, NULL) < 0) {
- if (errno == EINTR)
- continue;
- fprintf(stderr,
- "Can't select() on event channel (%s)\n",
- strerror(errno));
- break;
- }
-
- r = xenfb_poll(xenfb, &readfds);
- if (r == -2)
- xenfb_teardown(xenfb);
- if (r < 0)
- break;
- }
-
- rfbScreenCleanup(server);
- xenfb_delete(xenfb);
-
- return 0;
-}
diff -rupN xen-3.1.0-src.orig/tools/xenfb/xenfb.c xen-3.1.0-src.new/tools/xenfb/xenfb.c
--- xen-3.1.0-src.orig/tools/xenfb/xenfb.c 2007-08-23 11:05:27.000000000 -0400
+++ xen-3.1.0-src.new/tools/xenfb/xenfb.c 1969-12-31 19:00:00.000000000 -0500
@@ -1,826 +0,0 @@
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <xenctrl.h>
-#include <xen/io/xenbus.h>
-#include <xen/io/fbif.h>
-#include <xen/io/kbdif.h>
-#include <xen/io/protocols.h>
-#include <sys/select.h>
-#include <stdbool.h>
-#include <xen/linux/evtchn.h>
-#include <xen/event_channel.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <xs.h>
-
-#include "xenfb.h"
-
-// FIXME defend against malicious frontend?
-
-struct xenfb_device {
- const char *devicetype;
- char nodename[64]; /* backend xenstore dir */
- char otherend[64]; /* frontend xenstore dir */
- int otherend_id; /* frontend domid */
- enum xenbus_state state; /* backend state */
- void *page; /* shared page */
- evtchn_port_t port;
- struct xenfb_private *xenfb;
-};
-
-struct xenfb_private {
- struct xenfb pub;
- int evt_xch; /* event channel driver handle */
- int xc; /* hypervisor interface handle */
- struct xs_handle *xsh; /* xs daemon handle */
- struct xenfb_device fb, kbd;
- size_t fb_len; /* size of framebuffer */
- char protocol[64]; /* frontend protocol */
-};
-
-static void xenfb_detach_dom(struct xenfb_private *);
-
-static char *xenfb_path_in_dom(struct xs_handle *xsh,
- char *buf, size_t size,
- unsigned domid, const char *fmt, ...)
-{
- va_list ap;
- char *domp = xs_get_domain_path(xsh, domid);
- int n;
-
- if (domp == NULL)
- return NULL;
-
- n = snprintf(buf, size, "%s/", domp);
- free(domp);
- if (n >= size)
- return NULL;
-
- va_start(ap, fmt);
- n += vsnprintf(buf + n, size - n, fmt, ap);
- va_end(ap);
- if (n >= size)
- return NULL;
-
- return buf;
-}
-
-static int xenfb_xs_scanf1(struct xs_handle *xsh,
- const char *dir, const char *node,
- const char *fmt, void *dest)
-{
- char buf[1024];
- char *p;
- int ret;
-
- if (snprintf(buf, sizeof(buf), "%s/%s", dir, node) >= sizeof(buf)) {
- errno = ENOENT;
- return -1;
- }
- p = xs_read(xsh, XBT_NULL, buf, NULL);
- if (!p) {
- errno = ENOENT;
- return -1;
- }
- ret = sscanf(p, fmt, dest);
- free(p);
- if (ret != 1) {
- errno = EDOM;
- return -1;
- }
- return ret;
-}
-
-static int xenfb_xs_printf(struct xs_handle *xsh,
- const char *dir, const char *node, char *fmt, ...)
-{
- va_list ap;
- char key[1024];
- char val[1024];
- int n;
-
- if (snprintf(key, sizeof(key), "%s/%s", dir, node) >= sizeof(key)) {
- errno = ENOENT;
- return -1;
- }
-
- va_start(ap, fmt);
- n = vsnprintf(val, sizeof(val), fmt, ap);
- va_end(ap);
- if (n >= sizeof(val)) {
- errno = ENOSPC; /* close enough */
- return -1;
- }
-
- if (!xs_write(xsh, XBT_NULL, key, val, n))
- return -1;
- return 0;
-}
-
-static void xenfb_device_init(struct xenfb_device *dev,
- const char *type,
- struct xenfb_private *xenfb)
-{
- dev->devicetype = type;
- dev->otherend_id = -1;
- dev->port = -1;
- dev->xenfb = xenfb;
-}
-
-int xenfb_device_set_domain(struct xenfb_device *dev, int domid)
-{
- struct xenfb_private *xenfb = dev->xenfb;
-
- dev->otherend_id = domid;
-
- if (!xenfb_path_in_dom(xenfb->xsh,
- dev->otherend, sizeof(dev->otherend),
- domid, "device/%s/0", dev->devicetype)) {
- errno = ENOENT;
- return -1;
- }
- if (!xenfb_path_in_dom(xenfb->xsh,
- dev->nodename, sizeof(dev->nodename),
- 0, "backend/%s/%d/0", dev->devicetype, domid)) {
- errno = ENOENT;
- return -1;
- }
-
- return 0;
-}
-
-struct xenfb *xenfb_new(void)
-{
- struct xenfb_private *xenfb = malloc(sizeof(*xenfb));
- int serrno;
-
- if (xenfb == NULL)
- return NULL;
-
- memset(xenfb, 0, sizeof(*xenfb));
- xenfb->evt_xch = xenfb->xc = -1;
- xenfb_device_init(&xenfb->fb, "vfb", xenfb);
- xenfb_device_init(&xenfb->kbd, "vkbd", xenfb);
-
- xenfb->evt_xch = xc_evtchn_open();
- if (xenfb->evt_xch == -1)
- goto fail;
-
- xenfb->xc = xc_interface_open();
- if (xenfb->xc == -1)
- goto fail;
-
- xenfb->xsh = xs_daemon_open();
- if (!xenfb->xsh)
- goto fail;
-
- return &xenfb->pub;
-
- fail:
- serrno = errno;
- xenfb_delete(&xenfb->pub);
- errno = serrno;
- return NULL;
-}
-
-/* Remove the backend area in xenbus since the framebuffer really is
- going away. */
-void xenfb_teardown(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-
- xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);
- xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);
-}
-
-
-void xenfb_delete(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
-
- xenfb_detach_dom(xenfb);
- if (xenfb->xc >= 0)
- xc_interface_close(xenfb->xc);
- if (xenfb->evt_xch >= 0)
- xc_evtchn_close(xenfb->evt_xch);
- if (xenfb->xsh)
- xs_daemon_close(xenfb->xsh);
- free(xenfb);
-}
-
-static enum xenbus_state xenfb_read_state(struct xs_handle *xsh,
- const char *dir)
-{
- int ret, state;
-
- ret = xenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
- if (ret < 0)
- return XenbusStateUnknown;
-
- if ((unsigned)state > XenbusStateClosed)
- state = XenbusStateUnknown;
- return state;
-}
-
-static int xenfb_switch_state(struct xenfb_device *dev,
- enum xenbus_state state)
-{
- struct xs_handle *xsh = dev->xenfb->xsh;
-
- if (xenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
- return -1;
- dev->state = state;
- return 0;
-}
-
-static int xenfb_wait_for_state(struct xs_handle *xsh, const char *dir,
- unsigned awaited)
-{
- unsigned state, dummy;
- char **vec;
-
- awaited |= 1 << XenbusStateUnknown;
-
- for (;;) {
- state = xenfb_read_state(xsh, dir);
- if ((1 << state) & awaited)
- return state;
-
- vec = xs_read_watch(xsh, &dummy);
- if (!vec)
- return -1;
- free(vec);
- }
-}
-
-static int xenfb_wait_for_backend_creation(struct xenfb_device *dev)
-{
- struct xs_handle *xsh = dev->xenfb->xsh;
- int state;
-
- if (!xs_watch(xsh, dev->nodename, ""))
- return -1;
- state = xenfb_wait_for_state(xsh, dev->nodename,
- (1 << XenbusStateInitialising)
- | (1 << XenbusStateClosed)
-#if 1 /* TODO fudging state to permit restarting; to be removed */
- | (1 << XenbusStateInitWait)
- | (1 << XenbusStateConnected)
- | (1 << XenbusStateClosing)
-#endif
- );
- xs_unwatch(xsh, dev->nodename, "");
-
- switch (state) {
-#if 1
- case XenbusStateInitWait:
- case XenbusStateConnected:
- printf("Fudging state to %d\n", XenbusStateInitialising); /* FIXME */
-#endif
- case XenbusStateInitialising:
- case XenbusStateClosing:
- case XenbusStateClosed:
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static int xenfb_hotplug(struct xenfb_device *dev)
-{
- if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename,
- "hotplug-status", "connected"))
- return -1;
- return 0;
-}
-
-static int xenfb_wait_for_frontend_initialised(struct xenfb_device *dev)
-{
- switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
-#if 1 /* TODO fudging state to permit restarting; to be removed */
- (1 << XenbusStateInitialised)
- | (1 << XenbusStateConnected)
-#else
- 1 << XenbusStateInitialised,
-#endif
- )) {
-#if 1
- case XenbusStateConnected:
- printf("Fudging state to %d\n", XenbusStateInitialised); /* FIXME */
-#endif
- case XenbusStateInitialised:
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static void xenfb_copy_mfns(int mode, int count, unsigned long *dst, void *src)
-{
- uint32_t *src32 = src;
- uint64_t *src64 = src;
- int i;
-
- for (i = 0; i < count; i++)
- dst[i] = (mode == 32) ? src32[i] : src64[i];
-}
-
-static int xenfb_map_fb(struct xenfb_private *xenfb, int domid)
-{
- struct xenfb_page *page = xenfb->fb.page;
- int n_fbmfns;
- int n_fbdirs;
- unsigned long *pgmfns = NULL;
- unsigned long *fbmfns = NULL;
- void *map, *pd;
- int mode, ret = -1;
-
- /* default to native */
- pd = page->pd;
- mode = sizeof(unsigned long) * 8;
-
- if (0 == strlen(xenfb->protocol)) {
- /*
- * Undefined protocol, some guesswork needed.
- *
- * Old frontends which don't set the protocol use
- * one page directory only, thus pd[1] must be zero.
- * pd[1] of the 32bit struct layout and the lower
- * 32 bits of pd[0] of the 64bit struct layout have
- * the same location, so we can check that ...
- */
- uint32_t *ptr32 = NULL;
- uint32_t *ptr64 = NULL;
-#if defined(__i386__)
- ptr32 = (void*)page->pd;
- ptr64 = ((void*)page->pd) + 4;
-#elif defined(__x86_64__)
- ptr32 = ((void*)page->pd) - 4;
- ptr64 = (void*)page->pd;
-#endif
- if (ptr32) {
- if (0 == ptr32[1]) {
- mode = 32;
- pd = ptr32;
- } else {
- mode = 64;
- pd = ptr64;
- }
- }
-#if defined(__x86_64__)
- } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32)) {
- /* 64bit dom0, 32bit domU */
- mode = 32;
- pd = ((void*)page->pd) - 4;
-#elif defined(__i386__)
- } else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64)) {
- /* 32bit dom0, 64bit domU */
- mode = 64;
- pd = ((void*)page->pd) + 4;
-#endif
- }
-
- n_fbmfns = (xenfb->fb_len + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
- n_fbdirs = n_fbmfns * mode / 8;
- n_fbdirs = (n_fbdirs + (XC_PAGE_SIZE - 1)) / XC_PAGE_SIZE;
-
- pgmfns = malloc(sizeof(unsigned long) * n_fbdirs);
- fbmfns = malloc(sizeof(unsigned long) * n_fbmfns);
- if (!pgmfns || !fbmfns)
- goto out;
-
- /*
- * Bug alert: xc_map_foreign_batch() can fail partly and
- * return a non-null value. This is a design flaw. When it
- * happens, we happily continue here, and later crash on
- * access.
- */
- xenfb_copy_mfns(mode, n_fbdirs, pgmfns, pd);
- map = xc_map_foreign_batch(xenfb->xc, domid,
- PROT_READ, pgmfns, n_fbdirs);
- if (map == NULL)
- goto out;
- xenfb_copy_mfns(mode, n_fbmfns, fbmfns, map);
- munmap(map, n_fbdirs * XC_PAGE_SIZE);
-
- xenfb->pub.pixels = xc_map_foreign_batch(xenfb->xc, domid,
- PROT_READ | PROT_WRITE, fbmfns, n_fbmfns);
- if (xenfb->pub.pixels == NULL)
- goto out;
-
- ret = 0; /* all is fine */
-
- out:
- if (pgmfns)
- free(pgmfns);
- if (fbmfns)
- free(fbmfns);
- return ret;
-}
-
-static int xenfb_bind(struct xenfb_device *dev)
-{
- struct xenfb_private *xenfb = dev->xenfb;
- unsigned long mfn;
- evtchn_port_t evtchn;
-
- if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "page-ref", "%lu",
- &mfn) < 0)
- return -1;
- if (xenfb_xs_scanf1(xenfb->xsh, dev->otherend, "event-channel", "%u",
- &evtchn) < 0)
- return -1;
-
- dev->port = xc_evtchn_bind_interdomain(xenfb->evt_xch,
- dev->otherend_id, evtchn);
- if (dev->port == -1)
- return -1;
-
- dev->page = xc_map_foreign_range(xenfb->xc, dev->otherend_id,
- XC_PAGE_SIZE, PROT_READ | PROT_WRITE, mfn);
- if (dev->page == NULL)
- return -1;
-
- return 0;
-}
-
-static void xenfb_unbind(struct xenfb_device *dev)
-{
- if (dev->page) {
- munmap(dev->page, XC_PAGE_SIZE);
- dev->page = NULL;
- }
- if (dev->port >= 0) {
- xc_evtchn_unbind(dev->xenfb->evt_xch, dev->port);
- dev->port = -1;
- }
-}
-
-static int xenfb_wait_for_frontend_connected(struct xenfb_device *dev)
-{
- switch (xenfb_wait_for_state(dev->xenfb->xsh, dev->otherend,
- 1 << XenbusStateConnected)) {
- case XenbusStateConnected:
- break;
- default:
- return -1;
- }
-
- return 0;
-}
-
-static void xenfb_dev_fatal(struct xenfb_device *dev, int err,
- const char *fmt, ...)
-{
- struct xs_handle *xsh = dev->xenfb->xsh;
- va_list ap;
- char errdir[80];
- char buf[1024];
- int n;
-
- fprintf(stderr, "%s ", dev->nodename); /* somewhat crude */
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- if (err)
- fprintf(stderr, " (%s)", strerror(err));
- putc('\n', stderr);
-
- if (!xenfb_path_in_dom(xsh, errdir, sizeof(errdir), 0,
- "error/%s", dev->nodename))
- goto out; /* FIXME complain */
-
- va_start(ap, fmt);
- n = snprintf(buf, sizeof(buf), "%d ", err);
- snprintf(buf + n, sizeof(buf) - n, fmt, ap);
- va_end(ap);
-
- if (xenfb_xs_printf(xsh, buf, "error", "%s", buf) < 0)
- goto out; /* FIXME complain */
-
- out:
- xenfb_switch_state(dev, XenbusStateClosing);
-}
-
-int xenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- struct xs_handle *xsh = xenfb->xsh;
- int val, serrno;
- struct xenfb_page *fb_page;
-
- xenfb_detach_dom(xenfb);
-
- xenfb_device_set_domain(&xenfb->fb, domid);
- xenfb_device_set_domain(&xenfb->kbd, domid);
-
- if (xenfb_wait_for_backend_creation(&xenfb->fb) < 0)
- goto error;
- if (xenfb_wait_for_backend_creation(&xenfb->kbd) < 0)
- goto error;
-
- if (xenfb_xs_printf(xsh, xenfb->kbd.nodename, "feature-abs-pointer", "1"))
- goto error;
- if (xenfb_switch_state(&xenfb->fb, XenbusStateInitWait))
- goto error;
- if (xenfb_switch_state(&xenfb->kbd, XenbusStateInitWait))
- goto error;
-
- if (xenfb_hotplug(&xenfb->fb) < 0)
- goto error;
- if (xenfb_hotplug(&xenfb->kbd) < 0)
- goto error;
-
- if (!xs_watch(xsh, xenfb->fb.otherend, ""))
- goto error;
- if (!xs_watch(xsh, xenfb->kbd.otherend, ""))
- goto error;
-
- if (xenfb_wait_for_frontend_initialised(&xenfb->fb) < 0)
- goto error;
- if (xenfb_wait_for_frontend_initialised(&xenfb->kbd) < 0)
- goto error;
-
- if (xenfb_bind(&xenfb->fb) < 0)
- goto error;
- if (xenfb_bind(&xenfb->kbd) < 0)
- goto error;
-
- if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "feature-update",
- "%d", &val) < 0)
- val = 0;
- if (!val) {
- errno = ENOTSUP;
- goto error;
- }
- if (xenfb_xs_scanf1(xsh, xenfb->fb.otherend, "protocol", "%63s",
- xenfb->protocol) < 0)
- xenfb->protocol[0] = '\0';
- xenfb_xs_printf(xsh, xenfb->fb.nodename, "request-update", "1");
-
- /* TODO check for permitted ranges */
- fb_page = xenfb->fb.page;
- xenfb->pub.depth = fb_page->depth;
- xenfb->pub.width = fb_page->width;
- xenfb->pub.height = fb_page->height;
- /* TODO check for consistency with the above */
- xenfb->fb_len = fb_page->mem_length;
- xenfb->pub.row_stride = fb_page->line_length;
-
- if (xenfb_map_fb(xenfb, domid) < 0)
- goto error;
-
- if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected))
- goto error;
- if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected))
- goto error;
-
- if (xenfb_wait_for_frontend_connected(&xenfb->kbd) < 0)
- goto error;
- if (xenfb_xs_scanf1(xsh, xenfb->kbd.otherend, "request-abs-pointer",
- "%d", &val) < 0)
- val = 0;
- xenfb->pub.abs_pointer_wanted = val;
-
- return 0;
-
- error:
- serrno = errno;
- xenfb_detach_dom(xenfb);
- xenfb_dev_fatal(&xenfb->fb, serrno, "on fire");
- xenfb_dev_fatal(&xenfb->kbd, serrno, "on fire");
- errno = serrno;
- return -1;
-}
-
-static void xenfb_detach_dom(struct xenfb_private *xenfb)
-{
- xenfb_unbind(&xenfb->fb);
- xenfb_unbind(&xenfb->kbd);
- if (xenfb->pub.pixels) {
- munmap(xenfb->pub.pixels, xenfb->fb_len);
- xenfb->pub.pixels = NULL;
- }
-}
-
-static void xenfb_on_fb_event(struct xenfb_private *xenfb)
-{
- uint32_t prod, cons;
- struct xenfb_page *page = xenfb->fb.page;
-
- prod = page->out_prod;
- if (prod == page->out_cons)
- return;
- rmb(); /* ensure we see ring contents up to prod */
- for (cons = page->out_cons; cons != prod; cons++) {
- union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);
-
- switch (event->type) {
- case XENFB_TYPE_UPDATE:
- if (xenfb->pub.update)
- xenfb->pub.update(&xenfb->pub,
- event->update.x, event->update.y,
- event->update.width, event->update.height);
- break;
- }
- }
- mb(); /* ensure we're done with ring contents */
- page->out_cons = cons;
- xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
-}
-
-static void xenfb_on_kbd_event(struct xenfb_private *xenfb)
-{
- struct xenkbd_page *page = xenfb->kbd.page;
-
- /* We don't understand any keyboard events, so just ignore them. */
- if (page->out_prod == page->out_cons)
- return;
- page->out_cons = page->out_prod;
- xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
-}
-
-static int xenfb_on_state_change(struct xenfb_device *dev)
-{
- enum xenbus_state state;
-
- state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);
-
- switch (state) {
- case XenbusStateUnknown:
- /* There was an error reading the frontend state. The
- domain has probably gone away; in any case, there's
- not much point in us continuing. */
- return -1;
- case XenbusStateInitialising:
- case XenbusStateInitWait:
- case XenbusStateInitialised:
- case XenbusStateConnected:
- break;
- case XenbusStateClosing:
- xenfb_unbind(dev);
- xenfb_switch_state(dev, state);
- break;
- case XenbusStateClosed:
- xenfb_switch_state(dev, state);
- }
- return 0;
-}
-
-int xenfb_dispatch_channel(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- evtchn_port_t port;
- port = xc_evtchn_pending(xenfb->evt_xch);
- if (port == -1)
- return -1;
-
- if (port == xenfb->fb.port)
- xenfb_on_fb_event(xenfb);
- else if (port == xenfb->kbd.port)
- xenfb_on_kbd_event(xenfb);
-
- if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
- return -1;
-
- return 0;
-}
-
-int xenfb_dispatch_store(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- unsigned dummy;
- char **vec;
- int r;
-
- vec = xs_read_watch(xenfb->xsh, &dummy);
- free(vec);
- r = xenfb_on_state_change(&xenfb->fb);
- if (r == 0)
- r = xenfb_on_state_change(&xenfb->kbd);
- if (r == -1)
- return -2;
-
- return 0;
-}
-
-
-/* Returns 0 normally, -1 on error, or -2 if the domain went away. */
-int xenfb_poll(struct xenfb *xenfb_pub, fd_set *readfds)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- int ret;
-
- if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) {
- if ((ret = xenfb_dispatch_channel(xenfb_pub)) < 0)
- return ret;
- }
-
- if (FD_ISSET(xs_fileno(xenfb->xsh), readfds)) {
- if ((ret = xenfb_dispatch_store(xenfb_pub)) < 0)
- return ret;
- }
-
- return 0;
-}
-
-int xenfb_select_fds(struct xenfb *xenfb_pub, fd_set *readfds)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- int fd1 = xc_evtchn_fd(xenfb->evt_xch);
- int fd2 = xs_fileno(xenfb->xsh);
-
- FD_SET(fd1, readfds);
- FD_SET(fd2, readfds);
- return fd1 > fd2 ? fd1 + 1 : fd2 + 1;
-}
-
-int xenfb_get_store_fd(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- return xs_fileno(xenfb->xsh);
-}
-
-int xenfb_get_channel_fd(struct xenfb *xenfb_pub)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- return xc_evtchn_fd(xenfb->evt_xch);
-}
-
-static int xenfb_kbd_event(struct xenfb_private *xenfb,
- union xenkbd_in_event *event)
-{
- uint32_t prod;
- struct xenkbd_page *page = xenfb->kbd.page;
-
- if (xenfb->kbd.state != XenbusStateConnected)
- return 0;
-
- prod = page->in_prod;
- if (prod - page->in_cons == XENKBD_IN_RING_LEN) {
- errno = EAGAIN;
- return -1;
- }
-
- mb(); /* ensure ring space available */
- XENKBD_IN_RING_REF(page, prod) = *event;
- wmb(); /* ensure ring contents visible */
- page->in_prod = prod + 1;
- return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);
-}
-
-int xenfb_send_key(struct xenfb *xenfb_pub, bool down, int keycode)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- union xenkbd_in_event event;
-
- memset(&event, 0, XENKBD_IN_EVENT_SIZE);
- event.type = XENKBD_TYPE_KEY;
- event.key.pressed = down ? 1 : 0;
- event.key.keycode = keycode;
-
- return xenfb_kbd_event(xenfb, &event);
-}
-
-int xenfb_send_motion(struct xenfb *xenfb_pub, int rel_x, int rel_y)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- union xenkbd_in_event event;
-
- memset(&event, 0, XENKBD_IN_EVENT_SIZE);
- event.type = XENKBD_TYPE_MOTION;
- event.motion.rel_x = rel_x;
- event.motion.rel_y = rel_y;
-
- return xenfb_kbd_event(xenfb, &event);
-}
-
-int xenfb_send_position(struct xenfb *xenfb_pub, int abs_x, int abs_y)
-{
- struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
- union xenkbd_in_event event;
-
- memset(&event, 0, XENKBD_IN_EVENT_SIZE);
- event.type = XENKBD_TYPE_POS;
- event.pos.abs_x = abs_x;
- event.pos.abs_y = abs_y;
-
- return xenfb_kbd_event(xenfb, &event);
-}
-/*
- * Local variables:
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
diff -rupN xen-3.1.0-src.orig/tools/xenfb/xenfb.h xen-3.1.0-src.new/tools/xenfb/xenfb.h
--- xen-3.1.0-src.orig/tools/xenfb/xenfb.h 2007-08-23 11:05:27.000000000 -0400
+++ xen-3.1.0-src.new/tools/xenfb/xenfb.h 1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-#ifndef _XENFB_H_
-#define _XENFB_H_
-
-#include <stdbool.h>
-#include <sys/types.h>
-
-struct xenfb
-{
- void *pixels;
-
- int row_stride;
- int depth;
- int width;
- int height;
- int abs_pointer_wanted;
-
- void *user_data;
-
- void (*update)(struct xenfb *xenfb, int x, int y, int width, int height);
-};
-
-struct xenfb *xenfb_new(void);
-void xenfb_delete(struct xenfb *xenfb);
-void xenfb_teardown(struct xenfb *xenfb);
-
-int xenfb_attach_dom(struct xenfb *xenfb, int domid);
-
-int xenfb_dispatch_store(struct xenfb *xenfb_pub);
-int xenfb_dispatch_channel(struct xenfb *xenfb_pub);
-int xenfb_select_fds(struct xenfb *xenfb, fd_set *readfds);
-int xenfb_poll(struct xenfb *xenfb, fd_set *readfds);
-int xenfb_get_store_fd(struct xenfb *xenfb_pub);
-int xenfb_get_channel_fd(struct xenfb *xenfb_pub);
-
-int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
-int xenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
-int xenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);
-
-#endif