diff -rupN xen-3.1.2-src.orig/tools/ioemu/hw/oldxenfb.c xen-3.1.2-src.new/tools/ioemu/hw/oldxenfb.c
--- xen-3.1.2-src.orig/tools/ioemu/hw/oldxenfb.c 1969-12-31 19:00:00.000000000 -0500
+++ xen-3.1.2-src.new/tools/ioemu/hw/oldxenfb.c 2007-12-01 14:54:46.000000000 -0500
@@ -0,0 +1,693 @@
+#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/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"
+#include "oldxenfb.h"
+#include "oldxenkbd.h"
+
+// FIXME defend against malicious frontend?
+
+/*
+ * NB our back-compat hack relies on these structs being the same size
+ * or smaller than the same named structs in xenfb.c, and having the
+ * same field offsets in both. Do not change this !
+ */
+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 oldxenfb_detach_dom(struct xenfb_private *);
+static int oldxenfb_fb_event(struct xenfb_private *, union xenfb_in_event *);
+
+static char *oldxenfb_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 oldxenfb_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 oldxenfb_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;
+}
+
+int oldxenfb_device_set_domain(struct xenfb_device *dev, int domid)
+{
+ struct xenfb_private *xenfb = dev->xenfb;
+
+ dev->otherend_id = domid;
+
+ if (!oldxenfb_path_in_dom(xenfb->xsh,
+ dev->otherend, sizeof(dev->otherend),
+ domid, "device/%s/0", dev->devicetype)) {
+ errno = ENOENT;
+ return -1;
+ }
+ if (!oldxenfb_path_in_dom(xenfb->xsh,
+ dev->nodename, sizeof(dev->nodename),
+ 0, "backend/%s/%d/0", dev->devicetype, domid)) {
+ errno = ENOENT;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static enum xenbus_state oldxenfb_read_state(struct xs_handle *xsh,
+ const char *dir)
+{
+ int ret, state;
+
+ ret = oldxenfb_xs_scanf1(xsh, dir, "state", "%d", &state);
+ if (ret < 0)
+ return XenbusStateUnknown;
+
+ if ((unsigned)state > XenbusStateClosed)
+ state = XenbusStateUnknown;
+ return state;
+}
+
+static int oldxenfb_switch_state(struct xenfb_device *dev,
+ enum xenbus_state state)
+{
+ struct xs_handle *xsh = dev->xenfb->xsh;
+
+ if (oldxenfb_xs_printf(xsh, dev->nodename, "state", "%d", state) < 0)
+ return -1;
+ dev->state = state;
+ return 0;
+}
+
+static void oldxenfb_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 oldxenfb_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;
+ int mode, ret = -1;
+
+ if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_NATIVE))
+ mode = sizeof(unsigned long) * 8;
+ else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32))
+ mode = 32;
+ else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64))
+ mode = 64;
+ else
+ return -1;
+
+ 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.
+ */
+ oldxenfb_copy_mfns(mode, n_fbdirs, pgmfns, page->pd);
+ map = xc_map_foreign_batch(xenfb->xc, domid,
+ PROT_READ, pgmfns, n_fbdirs);
+ if (map == NULL)
+ goto out;
+ oldxenfb_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 oldxenfb_bind(struct xenfb_device *dev)
+{
+ struct xenfb_private *xenfb = dev->xenfb;
+ unsigned long mfn;
+ evtchn_port_t evtchn;
+ char buf[64];
+ char *p, **vec;
+ unsigned dummy;
+
+ p = oldxenfb_path_in_dom(xenfb->xsh, buf, sizeof(buf),
+ dev->otherend_id, dev->devicetype);
+ if (!xs_watch(xenfb->xsh, p, ""))
+ return -1;
+ for (;;) {
+ if (oldxenfb_xs_scanf1(xenfb->xsh, p, "page-ref", "%lu",
+ &mfn) < 0) {
+ if (errno == ENOENT || errno == EAGAIN)
+ goto wait;
+ return -1;
+ }
+ if (oldxenfb_xs_scanf1(xenfb->xsh, p, "event-channel", "%u",
+ &evtchn) < 0) {
+ if (errno == ENOENT || errno == EAGAIN)
+ goto wait;
+ return -1;
+ }
+ break;
+
+ wait:
+ printf("Waiting...\n");
+ vec = xs_read_watch(xenfb->xsh, &dummy);
+ if (!vec)
+ return -1;
+ free(vec);
+ }
+
+ 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 oldxenfb_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 void oldxenfb_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 (!oldxenfb_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 (oldxenfb_xs_printf(xsh, buf, "error", "%s", buf) < 0)
+ goto out; /* FIXME complain */
+
+ out:
+ oldxenfb_switch_state(dev, XenbusStateClosing);
+}
+
+int oldxenfb_attach_dom(struct xenfb *xenfb_pub, int domid)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ struct xs_handle *xsh = xenfb->xsh;
+ int serrno;
+ struct xenfb_page *fb_page;
+ union xenfb_in_event event;
+
+ if (oldxenfb_bind(&xenfb->fb) < 0)
+ goto error;
+ if (oldxenfb_bind(&xenfb->kbd) < 0)
+ goto error;
+
+ if (oldxenfb_xs_scanf1(xsh, xenfb->fb.otherend, "protocol", "%63s",
+ xenfb->protocol) < 0)
+ xenfb->protocol[0] = '\0';
+
+ /* 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 (oldxenfb_map_fb(xenfb, domid) < 0)
+ goto error;
+
+ event.type = XENFB_TYPE_SET_EVENTS;
+ event.set_events.flags = XENFB_FLAG_UPDATE;
+ if (oldxenfb_fb_event(xenfb, &event))
+ goto error;
+
+ fprintf(stderr, "Old protocol attach complete\n");
+ return 0;
+
+ error:
+ fprintf(stderr, "Old protocol attach failed\n");
+ serrno = errno;
+ oldxenfb_detach_dom(xenfb);
+ oldxenfb_dev_fatal(&xenfb->fb, serrno, "on fire");
+ oldxenfb_dev_fatal(&xenfb->kbd, serrno, "on fire");
+ errno = serrno;
+ return -1;
+}
+
+static void oldxenfb_detach_dom(struct xenfb_private *xenfb)
+{
+ oldxenfb_unbind(&xenfb->fb);
+ oldxenfb_unbind(&xenfb->kbd);
+ if (xenfb->pub.pixels) {
+ munmap(xenfb->pub.pixels, xenfb->fb_len);
+ xenfb->pub.pixels = NULL;
+ }
+}
+
+static void oldxenfb_on_fb_event32(struct xenfb_private *xenfb)
+{
+ uint32_t prod, cons;
+ struct xenfb_page32 *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 oldxenfb_on_fb_event64(struct xenfb_private *xenfb)
+{
+ uint32_t prod, cons;
+ struct xenfb_page64 *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 oldxenfb_on_fb_event(struct xenfb_private *xenfb)
+{
+ int mode;
+ if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_NATIVE))
+ mode = sizeof(unsigned long) * 8;
+ else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32))
+ mode = 32;
+ else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64))
+ mode = 64;
+ else
+ return;
+
+ if (mode == 32)
+ oldxenfb_on_fb_event32(xenfb);
+ else
+ oldxenfb_on_fb_event64(xenfb);
+}
+
+static void oldxenfb_on_kbd_event(struct xenfb_private *xenfb)
+{
+ struct xenkbd_info *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 oldxenfb_on_state_change(struct xenfb_device *dev)
+{
+ enum xenbus_state state;
+
+ state = oldxenfb_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:
+ oldxenfb_unbind(dev);
+ oldxenfb_switch_state(dev, state);
+ break;
+ case XenbusStateClosed:
+ oldxenfb_switch_state(dev, state);
+ }
+ return 0;
+}
+
+
+int oldxenfb_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)
+ oldxenfb_on_fb_event(xenfb);
+ else if (port == xenfb->kbd.port)
+ oldxenfb_on_kbd_event(xenfb);
+
+ if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1)
+ return -1;
+
+ return 0;
+}
+
+int oldxenfb_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 = oldxenfb_on_state_change(&xenfb->fb);
+ if (r == 0)
+ r = oldxenfb_on_state_change(&xenfb->kbd);
+ if (r == -1)
+ return -2;
+
+ return 0;
+}
+
+
+static int oldxenfb_fb_event32(struct xenfb_private *xenfb,
+ union xenfb_in_event *event)
+{
+ uint32_t prod;
+ struct xenfb_page32 *page = xenfb->fb.page;
+
+ prod = page->in_prod;
+ if (prod - page->in_cons == XENFB_IN_RING_LEN) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ mb(); /* ensure ring space available */
+ XENFB_IN_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->in_prod = prod + 1;
+ return xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
+}
+
+static int oldxenfb_fb_event64(struct xenfb_private *xenfb,
+ union xenfb_in_event *event)
+{
+ uint32_t prod;
+ struct xenfb_page64 *page = xenfb->fb.page;
+
+ prod = page->in_prod;
+ if (prod - page->in_cons == XENFB_IN_RING_LEN) {
+ errno = EAGAIN;
+ return -1;
+ }
+
+ mb(); /* ensure ring space available */
+ XENFB_IN_RING_REF(page, prod) = *event;
+ wmb(); /* ensure ring contents visible */
+ page->in_prod = prod + 1;
+ return xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);
+}
+
+static int oldxenfb_fb_event(struct xenfb_private *xenfb,
+ union xenfb_in_event *event)
+{
+ int mode;
+ if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_NATIVE))
+ mode = sizeof(unsigned long) * 8;
+ else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_32))
+ mode = 32;
+ else if (0 == strcmp(xenfb->protocol, XEN_IO_PROTO_ABI_X86_64))
+ mode = 64;
+ else
+ return -1;
+
+ if (mode == 32)
+ return oldxenfb_fb_event32(xenfb, event);
+ else
+ return oldxenfb_fb_event64(xenfb, event);
+}
+
+
+static int oldxenfb_kbd_event(struct xenfb_private *xenfb,
+ union xenkbd_in_event *event)
+{
+ uint32_t prod;
+ struct xenkbd_info *page = xenfb->kbd.page;
+
+ 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 oldxenfb_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 oldxenfb_kbd_event(xenfb, &event);
+}
+
+int oldxenfb_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 oldxenfb_kbd_event(xenfb, &event);
+}
+
+
+int xenfb_using_old_protocol(struct xenfb *xenfb_pub)
+{
+ struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
+ struct xs_handle *xsh = xenfb->xsh;
+ char buf[64];
+ char *p, *v, **vec;
+ enum xenbus_state state;
+ unsigned dummy;
+ int ret;
+
+ p = oldxenfb_path_in_dom(xsh, buf, sizeof(buf),
+ xenfb->fb.otherend_id, "vfb/page-ref");
+ if (!xs_watch(xsh, p, ""))
+ return -1;
+
+ for (;;) {
+ state = oldxenfb_read_state(xsh, xenfb->fb.otherend);
+ if (state == XenbusStateUnknown) {
+ ret = -1;
+ break;
+ }
+ if (state > XenbusStateInitialising) {
+ ret = 0; /* frontend talks xenbus protocol */
+ break;
+ }
+
+ v = xs_read(xsh, XBT_NULL, p, NULL);
+ free(v);
+ if (v) {
+ ret = 1; /* frontend talks old protocol */
+ break;
+ }
+
+ vec = xs_read_watch(xsh, &dummy);
+ if (!vec) {
+ ret = -1;
+ break;
+ }
+ free(vec);
+ }
+
+ xs_unwatch(xsh, p, "");
+ return ret;
+}
diff -rupN xen-3.1.2-src.orig/tools/ioemu/hw/oldxenfb.h xen-3.1.2-src.new/tools/ioemu/hw/oldxenfb.h
--- xen-3.1.2-src.orig/tools/ioemu/hw/oldxenfb.h 1969-12-31 19:00:00.000000000 -0500
+++ xen-3.1.2-src.new/tools/ioemu/hw/oldxenfb.h 2007-12-01 14:54:46.000000000 -0500
@@ -0,0 +1,133 @@
+/*
+ * linux/include/linux/xenfb.h -- Xen virtual frame buffer device
+ *
+ * Copyright (C) 2005
+ *
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef _LINUX_XENFB_H
+#define _LINUX_XENFB_H
+
+#include <asm/types.h>
+
+/* out events */
+
+#define XENFB_OUT_EVENT_SIZE 40
+
+#define XENFB_TYPE_MOTION 1
+#define XENFB_TYPE_UPDATE 2
+
+struct xenfb_motion /* currently unused */
+{
+ __u8 type; /* XENFB_TYPE_MOTION */
+ __u16 x; /* The new x coordinate */
+ __u16 y; /* The new y coordinate */
+};
+
+struct xenfb_update
+{
+ __u8 type; /* XENFB_TYPE_UPDATE */
+ __u16 x; /* source x */
+ __u16 y; /* source y */
+ __u16 width; /* rect width */
+ __u16 height; /* rect height */
+};
+
+union xenfb_out_event
+{
+ __u8 type;
+ struct xenfb_motion motion;
+ struct xenfb_update update;
+ char _[XENFB_OUT_EVENT_SIZE];
+};
+
+/* in events */
+
+#define XENFB_IN_EVENT_SIZE 40
+
+#define XENFB_TYPE_SET_EVENTS 1
+
+#define XENFB_FLAG_MOTION 1
+#define XENFB_FLAG_UPDATE 2
+#define XENFB_FLAG_COPY 4
+#define XENFB_FLAG_FILL 8
+
+struct xenfb_set_events
+{
+ __u8 type; /* XENFB_TYPE_SET_EVENTS */
+ __u32 flags; /* combination of XENFB_FLAG_* */
+};
+
+union xenfb_in_event
+{
+ __u8 type;
+ struct xenfb_set_events set_events;
+ char _[XENFB_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENFB_IN_RING_SIZE 1024
+#define XENFB_IN_RING_LEN (XENFB_IN_RING_SIZE / XENFB_IN_EVENT_SIZE)
+#define XENFB_IN_RING_OFFS 1024
+#define XENFB_IN_RING(page) \
+ ((union xenfb_in_event *)((char *)(page) + XENFB_IN_RING_OFFS))
+#define XENFB_IN_RING_REF(page, idx) \
+ (XENFB_IN_RING((page))[(idx) % XENFB_IN_RING_LEN])
+
+#define XENFB_OUT_RING_SIZE 2048
+#define XENFB_OUT_RING_LEN (XENFB_OUT_RING_SIZE / XENFB_OUT_EVENT_SIZE)
+#define XENFB_OUT_RING_OFFS (XENFB_IN_RING_OFFS + XENFB_IN_RING_SIZE)
+#define XENFB_OUT_RING(page) \
+ ((union xenfb_out_event *)((char *)(page) + XENFB_OUT_RING_OFFS))
+#define XENFB_OUT_RING_REF(page, idx) \
+ (XENFB_OUT_RING((page))[(idx) % XENFB_OUT_RING_LEN])
+
+struct xenfb_page
+{
+ __u16 width; /* the width of the framebuffer (in pixels) */
+ __u16 height; /* the height of the framebuffer (in pixels) */
+ __u32 line_length; /* the length of a row of pixels (in bytes) */
+ __u32 mem_length; /* the length of the framebuffer (in bytes) */
+ __u8 depth; /* the depth of a pixel (in bits) */
+
+ unsigned long pd[2]; /* FIXME rename to pgdir? */
+ /* FIXME pd[1] unused at this time, shrink? */
+};
+
+struct xenfb_page32
+{
+ __u16 width; /* the width of the framebuffer (in pixels) */
+ __u16 height; /* the height of the framebuffer (in pixels) */
+ __u32 line_length; /* the length of a row of pixels (in bytes) */
+ __u32 mem_length; /* the length of the framebuffer (in bytes) */
+ __u8 depth; /* the depth of a pixel (in bits) */
+
+ __u32 pd[2]; /* FIXME rename to pgdir? */
+ /* FIXME pd[1] unused at this time, shrink? */
+
+ __u32 in_cons, in_prod;
+ __u32 out_cons, out_prod;
+};
+
+struct xenfb_page64
+{
+ __u16 width; /* the width of the framebuffer (in pixels) */
+ __u16 height; /* the height of the framebuffer (in pixels) */
+ __u32 line_length; /* the length of a row of pixels (in bytes) */
+ __u32 mem_length; /* the length of the framebuffer (in bytes) */
+ __u8 depth; /* the depth of a pixel (in bits) */
+
+ __u64 pd[2]; /* FIXME rename to pgdir? */
+ /* FIXME pd[1] unused at this time, shrink? */
+
+ __u32 in_cons, in_prod;
+ __u32 out_cons, out_prod;
+};
+
+#endif
diff -rupN xen-3.1.2-src.orig/tools/ioemu/hw/oldxenkbd.h xen-3.1.2-src.new/tools/ioemu/hw/oldxenkbd.h
--- xen-3.1.2-src.orig/tools/ioemu/hw/oldxenkbd.h 1969-12-31 19:00:00.000000000 -0500
+++ xen-3.1.2-src.new/tools/ioemu/hw/oldxenkbd.h 2007-12-01 14:54:46.000000000 -0500
@@ -0,0 +1,92 @@
+/*
+ * linux/include/linux/xenkbd.h -- Xen virtual keyboard/mouse
+ *
+ * Copyright (C) 2005
+ *
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#ifndef _LINUX_XENKBD_H
+#define _LINUX_XENKBD_H
+
+#include <asm/types.h>
+
+/* in events */
+
+#define XENKBD_IN_EVENT_SIZE 40
+
+#define XENKBD_TYPE_MOTION 1 /* mouse movement event */
+#define XENKBD_TYPE_BUTTON 2 /* mouse button event */
+#define XENKBD_TYPE_KEY 3 /* keyboard event */
+
+struct xenkbd_motion
+{
+ __u8 type; /* XENKBD_TYPE_MOTION */
+ __s16 rel_x; /* relative X motion */
+ __s16 rel_y; /* relative Y motion */
+};
+
+struct xenkbd_button
+{
+ __u8 type; /* XENKBD_TYPE_BUTTON */
+ __u8 pressed; /* 1 if pressed; 0 otherwise */
+ __u8 button; /* the button (0, 1, 2 is right, middle, left) */
+};
+
+struct xenkbd_key
+{
+ __u8 type; /* XENKBD_TYPE_KEY */
+ __u8 pressed; /* 1 if pressed; 0 otherwise */
+ __u16 keycode; /* KEY_* from linux/input.h */
+};
+
+union xenkbd_in_event
+{
+ __u8 type;
+ struct xenkbd_motion motion;
+ struct xenkbd_button button;
+ struct xenkbd_key key;
+ char _[XENKBD_IN_EVENT_SIZE];
+};
+
+/* out events */
+
+#define XENKBD_OUT_EVENT_SIZE 40
+
+union xenkbd_out_event
+{
+ __u8 type;
+ char _[XENKBD_OUT_EVENT_SIZE];
+};
+
+/* shared page */
+
+#define XENKBD_IN_RING_SIZE 2048
+#define XENKBD_IN_RING_LEN (XENKBD_IN_RING_SIZE / XENKBD_IN_EVENT_SIZE)
+#define XENKBD_IN_RING_OFFS 1024
+#define XENKBD_IN_RING(page) \
+ ((union xenkbd_in_event *)((char *)(page) + XENKBD_IN_RING_OFFS))
+#define XENKBD_IN_RING_REF(page, idx) \
+ (XENKBD_IN_RING((page))[(idx) % XENKBD_IN_RING_LEN])
+
+#define XENKBD_OUT_RING_SIZE 1024
+#define XENKBD_OUT_RING_LEN (XENKBD_OUT_RING_SIZE / XENKBD_OUT_EVENT_SIZE)
+#define XENKBD_OUT_RING_OFFS (XENKBD_IN_RING_OFFS + XENKBD_IN_RING_SIZE)
+#define XENKBD_OUT_RING(page) \
+ ((union xenkbd_out_event *)((char *)(page) + XENKBD_OUT_RING_OFFS))
+#define XENKBD_OUT_RING_REF(page, idx) \
+ (XENKBD_OUT_RING((page))[(idx) % XENKBD_OUT_RING_LEN])
+
+struct xenkbd_info
+{
+ __u32 in_cons, in_prod;
+ __u32 out_cons, out_prod;
+};
+
+void xenkbd_resume(void);
+
+#endif
diff -rupN xen-3.1.2-src.orig/tools/ioemu/hw/xenfb.c xen-3.1.2-src.new/tools/ioemu/hw/xenfb.c
--- xen-3.1.2-src.orig/tools/ioemu/hw/xenfb.c 2007-12-01 14:54:37.000000000 -0500
+++ xen-3.1.2-src.new/tools/ioemu/hw/xenfb.c 2007-12-01 14:54:46.000000000 -0500
@@ -41,6 +41,7 @@ struct xenfb_private {
struct xenfb_device fb, kbd;
size_t fb_len; /* size of framebuffer */
char protocol[64]; /* frontend protocol */
+ int oldprotocol; /* Legacy FC6 compat */
};
static void xenfb_detach_dom(struct xenfb_private *);
@@ -545,6 +546,15 @@ int xenfb_attach_dom(struct xenfb *xenfb
if (!xs_watch(xsh, xenfb->kbd.otherend, ""))
goto error;
+ /* !!! FC-5/6 guest compatability - not upstream !!! */
+ if (xenfb_using_old_protocol(xenfb_pub)) {
+ fprintf(stderr, "Switching to old protocol\n");
+ xenfb->oldprotocol = 1;
+ return oldxenfb_attach_dom(xenfb_pub, domid);
+ } else {
+ fprintf(stderr, "Sticking to new protocol\n");
+ }
+
if (xenfb_wait_for_frontend_initialised(&xenfb->fb) < 0)
goto error;
if (xenfb_wait_for_frontend_initialised(&xenfb->kbd) < 0)
@@ -680,6 +690,10 @@ int xenfb_dispatch_channel(struct xenfb
{
struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
evtchn_port_t port;
+
+ if (xenfb->oldprotocol)
+ return oldxenfb_dispatch_channel(xenfb_pub);
+
port = xc_evtchn_pending(xenfb->evt_xch);
if (port == -1)
return -1;
@@ -702,6 +716,9 @@ int xenfb_dispatch_store(struct xenfb *x
char **vec;
int r;
+ if (xenfb->oldprotocol)
+ return oldxenfb_dispatch_store(xenfb_pub);
+
vec = xs_read_watch(xenfb->xsh, &dummy);
free(vec);
r = xenfb_on_state_change(&xenfb->fb);
@@ -783,6 +800,9 @@ int xenfb_send_key(struct xenfb *xenfb_p
struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
union xenkbd_in_event event;
+ if (xenfb->oldprotocol)
+ return oldxenfb_send_key(xenfb_pub, down, keycode);
+
memset(&event, 0, XENKBD_IN_EVENT_SIZE);
event.type = XENKBD_TYPE_KEY;
event.key.pressed = down ? 1 : 0;
@@ -796,6 +816,9 @@ int xenfb_send_motion(struct xenfb *xenf
struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
union xenkbd_in_event event;
+ if (xenfb->oldprotocol)
+ return oldxenfb_send_motion(xenfb_pub, rel_x, rel_y);
+
memset(&event, 0, XENKBD_IN_EVENT_SIZE);
event.type = XENKBD_TYPE_MOTION;
event.motion.rel_x = rel_x;
@@ -809,6 +832,9 @@ int xenfb_send_position(struct xenfb *xe
struct xenfb_private *xenfb = (struct xenfb_private *)xenfb_pub;
union xenkbd_in_event event;
+ if (xenfb->oldprotocol)
+ return -1;
+
memset(&event, 0, XENKBD_IN_EVENT_SIZE);
event.type = XENKBD_TYPE_POS;
event.pos.abs_x = abs_x;
diff -rupN xen-3.1.2-src.orig/tools/ioemu/hw/xenfb.h xen-3.1.2-src.new/tools/ioemu/hw/xenfb.h
--- xen-3.1.2-src.orig/tools/ioemu/hw/xenfb.h 2007-12-01 14:54:37.000000000 -0500
+++ xen-3.1.2-src.new/tools/ioemu/hw/xenfb.h 2007-12-01 14:54:46.000000000 -0500
@@ -36,4 +36,18 @@ int xenfb_send_key(struct xenfb *xenfb,
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);
+/* Detect if using old FC5/6 guest protocol */
+int xenfb_using_old_protocol(struct xenfb *xenfb_pub);
+
+/* Pass-through legacy handlers */
+int oldxenfb_attach_dom(struct xenfb *xenfb, int domid);
+
+int oldxenfb_dispatch_store(struct xenfb *xenfb_pub);
+int oldxenfb_dispatch_channel(struct xenfb *xenfb_pub);
+
+int oldxenfb_send_key(struct xenfb *xenfb, bool down, int keycode);
+int oldxenfb_send_motion(struct xenfb *xenfb, int rel_x, int rel_y);
+int oldxenfb_send_position(struct xenfb *xenfb, int abs_x, int abs_y);
+
+
#endif
diff -rupN xen-3.1.2-src.orig/tools/ioemu/Makefile.target xen-3.1.2-src.new/tools/ioemu/Makefile.target
--- xen-3.1.2-src.orig/tools/ioemu/Makefile.target 2007-12-01 14:54:37.000000000 -0500
+++ xen-3.1.2-src.new/tools/ioemu/Makefile.target 2007-12-01 14:54:46.000000000 -0500
@@ -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.o
+VL_OBJS+= xenfb.o oldxenfb.o
VL_OBJS+= tpm_tis.o
DEFINES += -DHAS_AUDIO
endif
diff -rupN xen-3.1.2-src.orig/tools/python/xen/xend/server/vfbif.py xen-3.1.2-src.new/tools/python/xen/xend/server/vfbif.py
--- xen-3.1.2-src.orig/tools/python/xen/xend/server/vfbif.py 2007-12-01 14:53:45.000000000 -0500
+++ xen-3.1.2-src.new/tools/python/xen/xend/server/vfbif.py 2007-12-01 14:54:46.000000000 -0500
@@ -50,7 +50,11 @@ class VfbifController(DevController):
if self.vm.info.is_hvm():
# is HVM, so qemu-dm will handle the vfb.
return
-
+
+ # old frontend compatibility
+ self.vm._writeDom("console/use_graphics", "1")
+ # /old
+
args = [ xen.util.auxbin.pathTo("qemu-dm"),
"-M", "xenpv",
"-d", "%d" % self.vm.getDomid(),
diff -rupN xen-3.1.2-src.orig/tools/python/xen/xend/XendConfig.py xen-3.1.2-src.new/tools/python/xen/xend/XendConfig.py
--- xen-3.1.2-src.orig/tools/python/xen/xend/XendConfig.py 2007-11-14 18:35:27.000000000 -0500
+++ xen-3.1.2-src.new/tools/python/xen/xend/XendConfig.py 2007-12-01 14:54:46.000000000 -0500
@@ -712,7 +712,7 @@ class XendConfig(dict):
self['vtpm_refs'] = cfg.get('vtpm_refs', [])
# coalesce hvm vnc frame buffer with vfb config
- if self.is_hvm() and int(self['platform'].get('vnc', 0)) != 0:
+ if int(self['platform'].get('vnc', 0)) != 0:
# add vfb device if it isn't there already
has_rfb = False
for console_uuid in self['console_refs']:
@@ -727,7 +727,7 @@ class XendConfig(dict):
dev_config = ['vfb']
# copy VNC related params from platform config to vfb dev conf
for key in ['vncpasswd', 'vncunused', 'vncdisplay',
- 'vnclisten']:
+ 'vnclisten', 'keymap']:
if key in self['platform']:
dev_config.append([key, self['platform'][key]])
diff -rupN xen-3.1.2-src.orig/tools/python/xen/xm/create.py xen-3.1.2-src.new/tools/python/xen/xm/create.py
--- xen-3.1.2-src.orig/tools/python/xen/xm/create.py 2007-11-14 18:35:27.000000000 -0500
+++ xen-3.1.2-src.new/tools/python/xen/xm/create.py 2007-12-01 14:54:46.000000000 -0500
@@ -610,7 +610,7 @@ def configure_vfbs(config_devs, vals):
d['type'] = 'sdl'
for (k,v) in d.iteritems():
if not k in [ 'vnclisten', 'vncunused', 'vncdisplay', 'display',
- 'xauthority', 'type', 'vncpasswd' ]:
+ 'xauthority', 'type', 'vncpasswd', 'keymap' ]:
err("configuration option %s unknown to vfbs" % k)
config.append([k,v])
if not d.has_key("keymap"):