From 94aa64e639992b8db20e9cbec602d5c21d7e07df Mon Sep 17 00:00:00 2001 From: Daniel P. Berrange Date: Aug 28 2007 21:50:58 +0000 Subject: Merge PVFB into QEMU. Backport VNC auth TLS/x509 support --- diff --git a/.cvsignore b/.cvsignore index 56ed453..bb6cd4b 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,2 +1 @@ -LibVNCServer-0.8.2.tar.gz xen-3.1.0-src.tgz diff --git a/sources b/sources index 0e18e98..a9226c8 100644 --- a/sources +++ b/sources @@ -1,2 +1 @@ -17a18e398af6c1730f72068022a152aa LibVNCServer-0.8.2.tar.gz b7ae1f652b071862ae4c90b72d549627 xen-3.1.0-src.tgz diff --git a/vnc-client-iterator.patch b/vnc-client-iterator.patch deleted file mode 100644 index fc0c454..0000000 --- a/vnc-client-iterator.patch +++ /dev/null @@ -1,91 +0,0 @@ -rfbClientIterator is swarming with bugs: -* Whoever added rfbClientListMutex didn't know what he was doing. -* Reference counting is broken -* The iterator normally skips closed entries (those with sock<0). But - rfbClientConnectionGone() neglects to reset cl->sock. -* Closed entries are *not* skipped when LIBVNCSERVER_HAVE_LIBPTHREAD - is undefined. - -diff -rup a/LibVNCServer-0.8.2/libvncserver/rfbserver.c b/LibVNCServer-0.8.2/libvncserver/rfbserver.c ---- a/LibVNCServer-0.8.2/libvncserver/rfbserver.c 2007-07-31 16:00:10.000000000 +0200 -+++ b/LibVNCServer-0.8.2/libvncserver/rfbserver.c 2007-07-31 15:14:47.000000000 +0200 -@@ -148,40 +148,42 @@ rfbGetClientIteratorWithClosed(rfbScreen - rfbClientPtr - rfbClientIteratorHead(rfbClientIteratorPtr i) - { -+ rfbClientPtr cl; -+ LOCK(rfbClientListMutex); - #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD - if(i->next != 0) { - rfbDecrClientRef(i->next); -- rfbIncrClientRef(i->screen->clientHead); - } -+ rfbIncrClientRef(i->screen->clientHead); - #endif -- LOCK(rfbClientListMutex); -- i->next = i->screen->clientHead; -+ cl = i->next = i->screen->clientHead; - UNLOCK(rfbClientListMutex); -- return i->next; -+ return cl; - } - - rfbClientPtr - rfbClientIteratorNext(rfbClientIteratorPtr i) - { -+ rfbClientPtr cl; -+ LOCK(rfbClientListMutex); - if(i->next == 0) { -- LOCK(rfbClientListMutex); - i->next = i->screen->clientHead; -- UNLOCK(rfbClientListMutex); - } else { -- IF_PTHREADS(rfbClientPtr cl = i->next); -+ IF_PTHREADS(cl = i->next); - i->next = i->next->next; - IF_PTHREADS(rfbDecrClientRef(cl)); - } - -+ if(!i->closedToo) -+ while(i->next && i->next->sock<0) -+ i->next = i->next->next; - #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD -- if(!i->closedToo) -- while(i->next && i->next->sock<0) -- i->next = i->next->next; -- if(i->next) -- rfbIncrClientRef(i->next); -+ if(i->next) -+ rfbIncrClientRef(i->next); - #endif -- -- return i->next; -+ cl = i->next; -+ UNLOCK(rfbClientListMutex); -+ return cl; - } - - void -@@ -474,8 +476,11 @@ rfbClientConnectionGone(rfbClientPtr cl) - if (cl->next) - cl->next->prev = cl->prev; - -- if(cl->sock>0) -+ if(cl->sock>=0) { -+ FD_CLR(cl->sock,&(cl->screen->allFds)); - close(cl->sock); -+ cl->sock = -1; -+ } - - if (cl->scaledScreen!=NULL) - cl->scaledScreen->scaledScreenRefCount--; -@@ -501,9 +506,6 @@ rfbClientConnectionGone(rfbClientPtr cl) - - UNLOCK(rfbClientListMutex); - -- if(cl->sock>=0) -- FD_CLR(cl->sock,&(cl->screen->allFds)); -- - cl->clientGoneHook(cl); - - rfbLog("Client %s gone\n",cl->host); diff --git a/vnc-double-cleanup.patch b/vnc-double-cleanup.patch deleted file mode 100644 index 297da38..0000000 --- a/vnc-double-cleanup.patch +++ /dev/null @@ -1,27 +0,0 @@ -Both clientInput() and rfbScreenCleanup() call -rfbClientConnectionGone(). This works only if clientInput() wins the -race with a sufficient margin to take the client off the list before -rfbScreenCleanup() sees it. Otherwise, rfbClientConnectionGone() is -called twice, with potentially disastrous results. - -diff -rup xen-3.1.0-src/LibVNCServer-0.8.2/libvncserver/main.c xen-3.1.0-hacked/LibVNCServer-0.8.2/libvncserver/main.c ---- xen-3.1.0-src/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-30 14:41:46.000000000 +0200 -+++ xen-3.1.0-hacked/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-31 15:52:51.000000000 +0200 -@@ -494,6 +494,8 @@ clientInput(void *data) - pthread_t output_thread; - pthread_create(&output_thread, NULL, clientOutput, (void *)cl); - -+ rfbIncrClientRef(cl); -+ - while (1) { - fd_set rfds, wfds, efds; - struct timeval tv; -@@ -555,7 +557,7 @@ clientInput(void *data) - UNLOCK(cl->updateMutex); - IF_PTHREADS(pthread_join(output_thread, NULL)); - -- rfbClientConnectionGone(cl); -+ rfbDecrClientRef(cl); - - return NULL; - } diff --git a/vnc-invalid-fd.patch b/vnc-invalid-fd.patch deleted file mode 100644 index 0e35fb6..0000000 --- a/vnc-invalid-fd.patch +++ /dev/null @@ -1,43 +0,0 @@ -When the socket has been closed already, cl->sock is -1. Don't pass -that to FD_SET() etc. - -diff -up a/LibVNCServer-0.8.2/libvncserver/main.c b/LibVNCServer-0.8.2/libvncserver/main.c ---- a/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-24 20:33:55.000000000 +0200 -+++ b/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-25 15:48:58.000000000 +0200 -@@ -497,9 +497,12 @@ clientInput(void *data) - int n, sock; - - LOCK(cl->updateMutex); -- sock = cl->sock; -+ sock = dup(cl->sock); - UNLOCK(cl->updateMutex); - -+ if (sock == -1) -+ break; -+ - FD_ZERO(&rfds); - FD_SET(sock, &rfds); - FD_ZERO(&efds); -@@ -515,11 +518,13 @@ clientInput(void *data) - n = select(sock + 1, &rfds, &wfds, &efds, &tv); - if (n < 0) { - rfbLogPerror("ReadExact: select"); -+ close(sock); - break; - } - if (n == 0) /* timeout */ - { - rfbSendFileTransferChunk(cl); -+ close(sock); - continue; - } - -@@ -530,6 +535,8 @@ clientInput(void *data) - if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &efds)) - rfbProcessClientMessage(cl); - -+ close(sock); -+ - LOCK(cl->updateMutex); - if (cl->sock == -1) { - UNLOCK(cl->updateMutex); diff --git a/vnc-ref-counting.patch b/vnc-ref-counting.patch deleted file mode 100644 index 2092c13..0000000 --- a/vnc-ref-counting.patch +++ /dev/null @@ -1,37 +0,0 @@ -Make the reference counting match the life range of cl. Before, other -threads could crash on accessing the prematurely freed cl. - -diff -up a/LibVNCServer-0.8.2/libvncserver/main.c b/LibVNCServer-0.8.2/libvncserver/main.c ---- a/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-24 20:33:55.000000000 +0200 -+++ b/LibVNCServer-0.8.2/libvncserver/main.c 2007-07-25 15:53:02.000000000 +0200 -@@ -441,11 +441,14 @@ clientOutput(void *data) - rfbBool haveUpdate; - sraRegion* updateRegion; - -+ rfbIncrClientRef(cl); -+ - while (1) { - haveUpdate = false; - while (!haveUpdate) { - if (cl->sock == -1) { - /* Client has disconnected. */ -+ rfbDecrClientRef(cl); - return NULL; - } - LOCK(cl->updateMutex); -@@ -473,13 +476,13 @@ clientOutput(void *data) - UNLOCK(cl->updateMutex); - - /* Now actually send the update. */ -- rfbIncrClientRef(cl); - rfbSendFramebufferUpdate(cl, updateRegion); -- rfbDecrClientRef(cl); - - sraRgnDestroy(updateRegion); - } - -+ rfbDecrClientRef(cl); -+ - /* Not reached. */ - return NULL; - } diff --git a/vnc-thread-fixes.patch b/vnc-thread-fixes.patch deleted file mode 100644 index 1cce39b..0000000 --- a/vnc-thread-fixes.patch +++ /dev/null @@ -1,89 +0,0 @@ -diff -ru xen-unstable-11405.orig/LibVNCServer-0.8.2/libvncserver/main.c xen-unstable-11405/LibVNCServer-0.8.2/libvncserver/main.c ---- xen-unstable-11405.orig/LibVNCServer-0.8.2/libvncserver/main.c 2006-05-28 16:38:26.000000000 -0400 -+++ xen-unstable-11405/LibVNCServer-0.8.2/libvncserver/main.c 2006-09-12 14:23:09.000000000 -0400 -@@ -454,13 +454,10 @@ - updateRegion = sraRgnCreateRgn(cl->modifiedRegion); - haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion); - sraRgnDestroy(updateRegion); -- } -- UNLOCK(cl->updateMutex); - -- if (!haveUpdate) { - WAIT(cl->updateCond, cl->updateMutex); -- UNLOCK(cl->updateMutex); /* we really needn't lock now. */ - } -+ UNLOCK(cl->updateMutex); - } - - /* OK, now, to save bandwidth, wait a little while for more -@@ -497,21 +494,25 @@ - while (1) { - fd_set rfds, wfds, efds; - struct timeval tv; -- int n; -+ int n, sock; -+ -+ LOCK(cl->updateMutex); -+ sock = cl->sock; -+ UNLOCK(cl->updateMutex); - - FD_ZERO(&rfds); -- FD_SET(cl->sock, &rfds); -+ FD_SET(sock, &rfds); - FD_ZERO(&efds); -- FD_SET(cl->sock, &efds); -+ FD_SET(sock, &efds); - - /* Are we transferring a file in the background? */ - FD_ZERO(&wfds); - if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1)) -- FD_SET(cl->sock, &wfds); -+ FD_SET(sock, &wfds); - - tv.tv_sec = 60; /* 1 minute */ - tv.tv_usec = 0; -- n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv); -+ n = select(sock + 1, &rfds, &wfds, &efds, &tv); - if (n < 0) { - rfbLogPerror("ReadExact: select"); - break; -@@ -523,16 +524,19 @@ - } - - /* We have some space on the transmit queue, send some data */ -- if (FD_ISSET(cl->sock, &wfds)) -+ if (FD_ISSET(sock, &wfds)) - rfbSendFileTransferChunk(cl); - -- if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds)) -+ if (FD_ISSET(sock, &rfds) || FD_ISSET(sock, &efds)) - rfbProcessClientMessage(cl); - -- if (cl->sock == -1) { -- /* Client has disconnected. */ -- break; -- } -+ LOCK(cl->updateMutex); -+ if (cl->sock == -1) { -+ UNLOCK(cl->updateMutex); -+ /* Client has disconnected. */ -+ break; -+ } -+ UNLOCK(cl->updateMutex); - } - - /* Get rid of the output thread. */ -diff -ru xen-unstable-11405.orig/LibVNCServer-0.8.2/libvncserver/rfbserver.c xen-unstable-11405/LibVNCServer-0.8.2/libvncserver/rfbserver.c ---- xen-unstable-11405.orig/LibVNCServer-0.8.2/libvncserver/rfbserver.c 2006-06-05 14:50:45.000000000 -0400 -+++ xen-unstable-11405/LibVNCServer-0.8.2/libvncserver/rfbserver.c 2006-09-12 13:02:06.000000000 -0400 -@@ -492,9 +492,9 @@ - do { - LOCK(cl->refCountMutex); - i=cl->refCount; -- UNLOCK(cl->refCountMutex); - if(i>0) - WAIT(cl->deleteCond,cl->refCountMutex); -+ UNLOCK(cl->refCountMutex); - } while(i>0); - } - #endif diff --git a/xen-pvfb-01-qemu-fv-machine.patch b/xen-pvfb-01-qemu-fv-machine.patch new file mode 100644 index 0000000..efb3f5c --- /dev/null +++ b/xen-pvfb-01-qemu-fv-machine.patch @@ -0,0 +1,619 @@ +diff -rupN xen-3.1.0-src.orig/tools/ioemu/hw/xen_machine_fv.c xen-3.1.0-src.new/tools/ioemu/hw/xen_machine_fv.c +--- xen-3.1.0-src.orig/tools/ioemu/hw/xen_machine_fv.c 1969-12-31 19:00:00.000000000 -0500 ++++ xen-3.1.0-src.new/tools/ioemu/hw/xen_machine_fv.c 2007-08-23 10:42:55.000000000 -0400 +@@ -0,0 +1,286 @@ ++/* ++ * QEMU Xen FV Machine ++ * ++ * Copyright (c) 2003-2007 Fabrice Bellard ++ * Copyright (c) 2007 Red Hat ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "vl.h" ++#include ++#include ++ ++#if defined(MAPCACHE) ++ ++#if defined(__i386__) ++#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ ++#define MCACHE_BUCKET_SHIFT 16 ++#elif defined(__x86_64__) ++#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ ++#define MCACHE_BUCKET_SHIFT 20 ++#endif ++ ++#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) ++ ++#define BITS_PER_LONG (sizeof(long)*8) ++#define BITS_TO_LONGS(bits) \ ++ (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) ++#define DECLARE_BITMAP(name,bits) \ ++ unsigned long name[BITS_TO_LONGS(bits)] ++#define test_bit(bit,map) \ ++ (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG)))) ++ ++struct map_cache { ++ unsigned long paddr_index; ++ uint8_t *vaddr_base; ++ DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT); ++}; ++ ++static struct map_cache *mapcache_entry; ++static unsigned long nr_buckets; ++ ++/* For most cases (>99.9%), the page address is the same. */ ++static unsigned long last_address_index = ~0UL; ++static uint8_t *last_address_vaddr; ++ ++static int qemu_map_cache_init(void) ++{ ++ unsigned long size; ++ ++ nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) + ++ (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >> ++ (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)); ++ fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx\n", nr_buckets); ++ ++ /* ++ * Use mmap() directly: lets us allocate a big hash table with no up-front ++ * cost in storage space. The OS will allocate memory only for the buckets ++ * that we actually use. All others will contain all zeroes. ++ */ ++ size = nr_buckets * sizeof(struct map_cache); ++ size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); ++ mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE, ++ MAP_SHARED|MAP_ANONYMOUS, 0, 0); ++ if (mapcache_entry == MAP_FAILED) { ++ errno = ENOMEM; ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void qemu_remap_bucket(struct map_cache *entry, ++ unsigned long address_index) ++{ ++ uint8_t *vaddr_base; ++ unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; ++ unsigned int i, j; ++ ++ if (entry->vaddr_base != NULL) { ++ errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); ++ if (errno) { ++ fprintf(logfile, "unmap fails %d\n", errno); ++ exit(-1); ++ } ++ } ++ ++ for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) ++ pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; ++ ++ vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, ++ pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); ++ if (vaddr_base == NULL) { ++ fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); ++ exit(-1); ++ } ++ ++ entry->vaddr_base = vaddr_base; ++ entry->paddr_index = address_index; ++ ++ for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) { ++ unsigned long word = 0; ++ j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ? ++ (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG; ++ while (j > 0) ++ word = (word << 1) | !(pfns[i + --j] & 0xF0000000UL); ++ entry->valid_mapping[i / BITS_PER_LONG] = word; ++ } ++} ++ ++uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) ++{ ++ struct map_cache *entry; ++ unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT; ++ unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1); ++ ++ if (address_index == last_address_index) ++ return last_address_vaddr + address_offset; ++ ++ entry = &mapcache_entry[address_index % nr_buckets]; ++ ++ if (entry->vaddr_base == NULL || entry->paddr_index != address_index || ++ !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) ++ qemu_remap_bucket(entry, address_index); ++ ++ if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) ++ return NULL; ++ ++ last_address_index = address_index; ++ last_address_vaddr = entry->vaddr_base; ++ ++ return last_address_vaddr + address_offset; ++} ++ ++void qemu_invalidate_map_cache(void) ++{ ++ unsigned long i; ++ ++ mapcache_lock(); ++ ++ for (i = 0; i < nr_buckets; i++) { ++ struct map_cache *entry = &mapcache_entry[i]; ++ ++ if (entry->vaddr_base == NULL) ++ continue; ++ ++ errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); ++ if (errno) { ++ fprintf(logfile, "unmap fails %d\n", errno); ++ exit(-1); ++ } ++ ++ entry->paddr_index = 0; ++ entry->vaddr_base = NULL; ++ } ++ ++ last_address_index = ~0UL; ++ last_address_vaddr = NULL; ++ ++ mapcache_unlock(); ++} ++ ++#endif /* defined(MAPCACHE) */ ++ ++ ++static void xen_init_fv(uint64_t ram_size, int vga_ram_size, char *boot_device, ++ DisplayState *ds, const char **fd_filename, ++ int snapshot, ++ const char *kernel_filename, ++ const char *kernel_cmdline, ++ const char *initrd_filename, time_t timeoffset) ++{ ++ unsigned long ioreq_pfn; ++ extern void *shared_page; ++ extern void *buffered_io_page; ++#ifdef __ia64__ ++ unsigned long nr_pages; ++ xen_pfn_t *page_array; ++ extern void *buffered_pio_page; ++#endif ++ ++#if defined(__i386__) || defined(__x86_64__) ++ ++ if (qemu_map_cache_init()) { ++ fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno); ++ exit(-1); ++ } ++ ++ xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn); ++ fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn); ++ shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, ++ PROT_READ|PROT_WRITE, ioreq_pfn); ++ if (shared_page == NULL) { ++ fprintf(logfile, "map shared IO page returned error %d\n", errno); ++ exit(-1); ++ } ++ ++ xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn); ++ fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn); ++ buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, ++ PROT_READ|PROT_WRITE, ioreq_pfn); ++ if (buffered_io_page == NULL) { ++ fprintf(logfile, "map buffered IO page returned error %d\n", errno); ++ exit(-1); ++ } ++ ++#elif defined(__ia64__) ++ ++ nr_pages = ram_size/PAGE_SIZE; ++ ++ page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t)); ++ if (page_array == NULL) { ++ fprintf(logfile, "malloc returned error %d\n", errno); ++ exit(-1); ++ } ++ ++ shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, ++ PROT_READ|PROT_WRITE, ++ IO_PAGE_START >> PAGE_SHIFT); ++ ++ buffered_io_page =xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, ++ PROT_READ|PROT_WRITE, ++ BUFFER_IO_PAGE_START >> PAGE_SHIFT); ++ ++ buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, ++ PROT_READ|PROT_WRITE, ++ BUFFER_PIO_PAGE_START >> PAGE_SHIFT); ++ ++ for (i = 0; i < nr_pages; i++) ++ page_array[i] = i; ++ ++ /* VTI will not use memory between 3G~4G, so we just pass a legal pfn ++ to make QEMU map continuous virtual memory space */ ++ if (ram_size > MMIO_START) { ++ for (i = 0 ; i < (MEM_G >> PAGE_SHIFT); i++) ++ page_array[(MMIO_START >> PAGE_SHIFT) + i] = ++ (STORE_PAGE_START >> PAGE_SHIFT); ++ } ++ ++ phys_ram_base = xc_map_foreign_batch(xc_handle, domid, ++ PROT_READ|PROT_WRITE, ++ page_array, nr_pages); ++ if (phys_ram_base == 0) { ++ fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); ++ exit(-1); ++ } ++ free(page_array); ++#endif ++ ++ timeoffset_get(); ++ ++ ++ pc_machine.init(ram_size, vga_ram_size, boot_device, ds, fd_filename, ++ snapshot, kernel_filename, kernel_cmdline, initrd_filename, timeoffset); ++} ++ ++QEMUMachine xenfv_machine = { ++ "xenfv", ++ "Xen Fully-virtualized PC", ++ xen_init_fv, ++}; ++ ++/* ++ * Local variables: ++ * indent-tabs-mode: nil ++ * c-indent-level: 4 ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * End: ++ */ +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-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/Makefile.target 2007-08-23 10:42:55.000000000 -0400 +@@ -369,6 +369,7 @@ VL_OBJS+= usb-uhci.o + VL_OBJS+= piix4acpi.o + VL_OBJS+= xenstore.o + VL_OBJS+= xen_platform.o ++VL_OBJS+= xen_machine_fv.o + VL_OBJS+= tpm_tis.o + DEFINES += -DHAS_AUDIO + endif +diff -rupN xen-3.1.0-src.orig/tools/ioemu/vl.c xen-3.1.0-src.new/tools/ioemu/vl.c +--- xen-3.1.0-src.orig/tools/ioemu/vl.c 2007-08-23 10:41:10.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.c 2007-08-23 10:45:27.000000000 -0400 +@@ -88,7 +88,6 @@ + + #include "exec-all.h" + +-#include + #define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup" + #define DEFAULT_BRIDGE "xenbr0" + +@@ -5694,8 +5693,12 @@ static void read_passwords(void) + void register_machines(void) + { + #if defined(TARGET_I386) ++#ifndef CONFIG_DM + qemu_register_machine(&pc_machine); + qemu_register_machine(&isapc_machine); ++#else ++ qemu_register_machine(&xenfv_machine); ++#endif + #elif defined(TARGET_PPC) + qemu_register_machine(&heathrow_machine); + qemu_register_machine(&core99_machine); +@@ -5910,156 +5913,6 @@ void suspend(int sig) + suspend_requested = 1; + } + +-#if defined(MAPCACHE) +- +-#if defined(__i386__) +-#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ +-#define MCACHE_BUCKET_SHIFT 16 +-#elif defined(__x86_64__) +-#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ +-#define MCACHE_BUCKET_SHIFT 20 +-#endif +- +-#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) +- +-#define BITS_PER_LONG (sizeof(long)*8) +-#define BITS_TO_LONGS(bits) \ +- (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +-#define DECLARE_BITMAP(name,bits) \ +- unsigned long name[BITS_TO_LONGS(bits)] +-#define test_bit(bit,map) \ +- (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG)))) +- +-struct map_cache { +- unsigned long paddr_index; +- uint8_t *vaddr_base; +- DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT); +-}; +- +-static struct map_cache *mapcache_entry; +-static unsigned long nr_buckets; +- +-/* For most cases (>99.9%), the page address is the same. */ +-static unsigned long last_address_index = ~0UL; +-static uint8_t *last_address_vaddr; +- +-static int qemu_map_cache_init(void) +-{ +- unsigned long size; +- +- nr_buckets = (((MAX_MCACHE_SIZE >> PAGE_SHIFT) + +- (1UL << (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)) - 1) >> +- (MCACHE_BUCKET_SHIFT - PAGE_SHIFT)); +- fprintf(logfile, "qemu_map_cache_init nr_buckets = %lx\n", nr_buckets); +- +- /* +- * Use mmap() directly: lets us allocate a big hash table with no up-front +- * cost in storage space. The OS will allocate memory only for the buckets +- * that we actually use. All others will contain all zeroes. +- */ +- size = nr_buckets * sizeof(struct map_cache); +- size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); +- mapcache_entry = mmap(NULL, size, PROT_READ|PROT_WRITE, +- MAP_SHARED|MAP_ANONYMOUS, 0, 0); +- if (mapcache_entry == MAP_FAILED) { +- errno = ENOMEM; +- return -1; +- } +- +- return 0; +-} +- +-static void qemu_remap_bucket(struct map_cache *entry, +- unsigned long address_index) +-{ +- uint8_t *vaddr_base; +- unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; +- unsigned int i, j; +- +- if (entry->vaddr_base != NULL) { +- errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); +- if (errno) { +- fprintf(logfile, "unmap fails %d\n", errno); +- exit(-1); +- } +- } +- +- for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) +- pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; +- +- vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, +- pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); +- if (vaddr_base == NULL) { +- fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); +- exit(-1); +- } +- +- entry->vaddr_base = vaddr_base; +- entry->paddr_index = address_index; +- +- for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) { +- unsigned long word = 0; +- j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ? +- (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG; +- while (j > 0) +- word = (word << 1) | !(pfns[i + --j] & 0xF0000000UL); +- entry->valid_mapping[i / BITS_PER_LONG] = word; +- } +-} +- +-uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) +-{ +- struct map_cache *entry; +- unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT; +- unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1); +- +- if (address_index == last_address_index) +- return last_address_vaddr + address_offset; +- +- entry = &mapcache_entry[address_index % nr_buckets]; +- +- if (entry->vaddr_base == NULL || entry->paddr_index != address_index || +- !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) +- qemu_remap_bucket(entry, address_index); +- +- if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) +- return NULL; +- +- last_address_index = address_index; +- last_address_vaddr = entry->vaddr_base; +- +- return last_address_vaddr + address_offset; +-} +- +-void qemu_invalidate_map_cache(void) +-{ +- unsigned long i; +- +- mapcache_lock(); +- +- for (i = 0; i < nr_buckets; i++) { +- struct map_cache *entry = &mapcache_entry[i]; +- +- if (entry->vaddr_base == NULL) +- continue; +- +- errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); +- if (errno) { +- fprintf(logfile, "unmap fails %d\n", errno); +- exit(-1); +- } +- +- entry->paddr_index = 0; +- entry->vaddr_base = NULL; +- } +- +- last_address_index = ~0UL; +- last_address_vaddr = NULL; +- +- mapcache_unlock(); +-} +- +-#endif /* defined(MAPCACHE) */ + + int main(int argc, char **argv) + { +@@ -6094,14 +5947,6 @@ int main(int argc, char **argv) + QEMUMachine *machine; + char usb_devices[MAX_USB_CMDLINE][128]; + int usb_devices_index; +- unsigned long ioreq_pfn; +- extern void *shared_page; +- extern void *buffered_io_page; +-#ifdef __ia64__ +- unsigned long nr_pages; +- xen_pfn_t *page_array; +- extern void *buffered_pio_page; +-#endif + + char qemu_dm_logfilename[64]; + +@@ -6586,6 +6431,7 @@ int main(int argc, char **argv) + + #ifdef CONFIG_DM + bdrv_init(); ++ xc_handle = xc_interface_open(); + xenstore_parse_domain_config(domid); + #endif /* CONFIG_DM */ + +@@ -6639,99 +6485,17 @@ int main(int argc, char **argv) + exit(1); + } + +-#if defined (__ia64__) +- if (ram_size > MMIO_START) +- ram_size += 1 * MEM_G; /* skip 3G-4G MMIO, LEGACY_IO_SPACE etc. */ +-#endif + + /* init the memory */ + phys_ram_size = ram_size + vga_ram_size + bios_size; + +-#ifdef CONFIG_DM +- +- xc_handle = xc_interface_open(); +- +-#if defined(__i386__) || defined(__x86_64__) +- +- if (qemu_map_cache_init()) { +- fprintf(logfile, "qemu_map_cache_init returned: error %d\n", errno); +- exit(-1); +- } +- +- xc_get_hvm_param(xc_handle, domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn); +- fprintf(logfile, "shared page at pfn %lx\n", ioreq_pfn); +- shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, +- PROT_READ|PROT_WRITE, ioreq_pfn); +- if (shared_page == NULL) { +- fprintf(logfile, "map shared IO page returned error %d\n", errno); +- exit(-1); +- } +- +- xc_get_hvm_param(xc_handle, domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn); +- fprintf(logfile, "buffered io page at pfn %lx\n", ioreq_pfn); +- buffered_io_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, +- PROT_READ|PROT_WRITE, ioreq_pfn); +- if (buffered_io_page == NULL) { +- fprintf(logfile, "map buffered IO page returned error %d\n", errno); +- exit(-1); +- } +- +-#elif defined(__ia64__) +- +- nr_pages = ram_size/PAGE_SIZE; +- +- page_array = (xen_pfn_t *)malloc(nr_pages * sizeof(xen_pfn_t)); +- if (page_array == NULL) { +- fprintf(logfile, "malloc returned error %d\n", errno); +- exit(-1); +- } +- +- shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, +- PROT_READ|PROT_WRITE, +- IO_PAGE_START >> PAGE_SHIFT); +- +- buffered_io_page =xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, +- PROT_READ|PROT_WRITE, +- BUFFER_IO_PAGE_START >> PAGE_SHIFT); +- +- buffered_pio_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, +- PROT_READ|PROT_WRITE, +- BUFFER_PIO_PAGE_START >> PAGE_SHIFT); +- +- for (i = 0; i < nr_pages; i++) +- page_array[i] = i; +- +- /* VTI will not use memory between 3G~4G, so we just pass a legal pfn +- to make QEMU map continuous virtual memory space */ +- if (ram_size > MMIO_START) { +- for (i = 0 ; i < (MEM_G >> PAGE_SHIFT); i++) +- page_array[(MMIO_START >> PAGE_SHIFT) + i] = +- (STORE_PAGE_START >> PAGE_SHIFT); +- } +- +- phys_ram_base = xc_map_foreign_batch(xc_handle, domid, +- PROT_READ|PROT_WRITE, +- page_array, nr_pages); +- if (phys_ram_base == 0) { +- fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno); +- exit(-1); +- } +- free(page_array); +-#endif +- +- timeoffset_get(); +- +-#else /* !CONFIG_DM */ +- ++#ifndef CONFIG_DM + phys_ram_base = qemu_vmalloc(phys_ram_size); + if (!phys_ram_base) { + fprintf(stderr, "Could not allocate physical memory\n"); + exit(1); + } + +-#endif /* !CONFIG_DM */ +- +-#ifndef CONFIG_DM + /* we always create the cdrom drive, even if no disk is there */ + bdrv_init(); + if (cdrom_index >= 0) { +diff -rupN xen-3.1.0-src.orig/tools/ioemu/vl.h xen-3.1.0-src.new/tools/ioemu/vl.h +--- xen-3.1.0-src.orig/tools/ioemu/vl.h 2007-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.h 2007-08-23 10:42:55.000000000 -0400 +@@ -966,6 +966,9 @@ extern void pci_piix4_acpi_init(PCIBus * + /* pc.c */ + extern QEMUMachine pc_machine; + extern QEMUMachine isapc_machine; ++#ifdef CONFIG_DM ++extern QEMUMachine xenfv_machine; ++#endif + extern int fd_bootchk; + + void ioport_set_a20(int enable); diff --git a/xen-pvfb-02-qemu-pv-machine.patch b/xen-pvfb-02-qemu-pv-machine.patch new file mode 100644 index 0000000..2476be4 --- /dev/null +++ b/xen-pvfb-02-qemu-pv-machine.patch @@ -0,0 +1,489 @@ +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 1969-12-31 19:00:00.000000000 -0500 ++++ xen-3.1.0-src.new/tools/ioemu/hw/xen_machine_pv.c 2007-08-23 10:52:15.000000000 -0400 +@@ -0,0 +1,231 @@ ++/* ++ * QEMU Xen PV Machine ++ * ++ * Copyright (c) 2007 Red Hat ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include "vl.h" ++#include "../../xenfb/xenfb.h" ++#include ++ ++/* A convenient function for munging pixels between different depths */ ++#define BLT(SRC_T,DST_T,RLS,GLS,BLS,RRS,GRS,BRS,RM,GM,BM) \ ++ for (line = y ; line < h ; line++) { \ ++ SRC_T *src = (SRC_T *)(xenfb->pixels + (line*xenfb->row_stride) + (x*xenfb->depth/8)); \ ++ DST_T *dst = (DST_T *)(ds->data + (line*ds->linesize) + (x*ds->depth/8)); \ ++ int col; \ ++ for (col = x ; col < w ; col++) { \ ++ *dst = (((*src >> RRS)&RM) << RLS) | \ ++ (((*src >> GRS)&GM) << GLS) | \ ++ (((*src >> GRS)&BM) << BLS); \ ++ src++; \ ++ dst++; \ ++ } \ ++ } ++ ++ ++/* This copies data from the guest framebuffer region, into QEMU's copy ++ * NB. QEMU's copy is stored in the pixel format of a) the local X server (SDL case) ++ * or b) the current VNC client pixel format. ++ */ ++static void xen_pvfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h) ++{ ++ DisplayState *ds = (DisplayState *)xenfb->user_data; ++ int line; ++ ++ if (xenfb->depth == ds->depth) { /* Perfect match can use fast path */ ++ for (line = y ; line < (y+h) ; line++) { ++ memcpy(ds->data + (line * ds->linesize) + (x*ds->depth/8), ++ xenfb->pixels + (line*xenfb->row_stride) + (x*xenfb->depth/8), ++ w * xenfb->depth/8); ++ } ++ } else { /* Mismatch requires slow pixel munging */ ++ if (xenfb->depth == 8) { ++ /* 8 bit source == r:3 g:3 b:2 */ ++ if (ds->depth == 16) { ++ BLT(uint8_t, uint16_t, 5, 2, 0, 11, 5, 0, 7, 7, 3); ++ } else if (ds->depth == 32) { ++ BLT(uint8_t, uint32_t, 5, 2, 0, 16, 8, 0, 7, 7, 3); ++ } ++ } else if (xenfb->depth == 16) { ++ /* 16 bit source == r:5 g:6 b:5 */ ++ if (ds->depth == 8) { ++ BLT(uint16_t, uint8_t, 11, 5, 0, 5, 2, 0, 31, 63, 31); ++ } else if (ds->depth == 32) { ++ BLT(uint16_t, uint32_t, 11, 5, 0, 16, 8, 0, 31, 63, 31); ++ } ++ } else if (xenfb->depth == 32) { ++ /* 32 bit source == r:8 g:8 b:8 (padding:8) */ ++ if (ds->depth == 8) { ++ BLT(uint32_t, uint8_t, 16, 8, 0, 5, 2, 0, 255, 255, 255); ++ } else if (ds->depth == 16) { ++ BLT(uint32_t, uint16_t, 16, 8, 0, 11, 5, 0, 255, 255, 255); ++ } ++ } ++ } ++ dpy_update(ds, x, y, w, h); ++} ++ ++ ++/* Send a keypress from the client to the guest OS */ ++static void xen_pvfb_put_keycode(void *opaque, int keycode) ++{ ++ struct xenfb *xenfb = (struct xenfb*)opaque; ++ xenfb_send_key(xenfb, keycode & 0x80 ? 0 : 1, keycode & 0x7f); ++} ++ ++/* Send a mouse event from the client to the guest OS */ ++static void xen_pvfb_mouse_event(void *opaque, ++ int dx, int dy, int dz, int button_state) ++{ ++ static int old_state = 0; ++ int i; ++ struct xenfb *xenfb = (struct xenfb*)opaque; ++ DisplayState *ds = (DisplayState *)xenfb->user_data; ++ if (xenfb->abs_pointer_wanted) ++ xenfb_send_position(xenfb, ++ dx*ds->width/0x7fff, ++ dy*ds->height/0x7fff); ++ else ++ xenfb_send_motion(xenfb, dx, dy); ++ ++ for (i = 0 ; i < 8 ; i++) { ++ int lastDown = old_state & (1 << i); ++ int down = button_state & (1 << i); ++ if (down == lastDown) ++ continue; ++ ++ if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0) ++ return; ++ } ++ old_state = button_state; ++} ++ ++/* QEMU display state changed, so refresh the framebuffer copy */ ++void xen_pvfb_update(void *opaque) ++{ ++ struct xenfb *xenfb = (struct xenfb *)opaque; ++ xen_pvfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); ++} ++ ++/* QEMU display state changed, so refresh the framebuffer copy */ ++void xen_pvfb_invalidate(void *opaque) ++{ ++ struct xenfb *xenfb = (struct xenfb *)opaque; ++ xen_pvfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height); ++} ++ ++/* Screen dump is not used in Xen, so no need to impl this ? */ ++void xen_pvfb_screen_dump(void *opaque, const char *name) { } ++ ++void xen_pvfb_dispatch_store(void *opaque) { ++ int ret; ++ if ((ret = xenfb_dispatch_store((struct xenfb *)opaque)) < 0) { ++ fprintf(stderr, "Failure while dispatching store: %d\n", ret); ++ exit(1); ++ } ++} ++ ++void xen_pvfb_dispatch_channel(void *opaque) { ++ int ret; ++ if ((ret = xenfb_dispatch_channel((struct xenfb *)opaque)) < 0) { ++ fprintf(stderr, "Failure while dispatching store: %d\n", ret); ++ exit(1); ++ } ++} ++ ++/* The Xen PV machine currently provides ++ * - a virtual framebuffer ++ * - .... ++ */ ++static void xen_init_pv(uint64_t ram_size, int vga_ram_size, char *boot_device, ++ DisplayState *ds, const char **fd_filename, ++ int snapshot, ++ const char *kernel_filename, ++ const char *kernel_cmdline, ++ const char *initrd_filename, time_t timeoffset) ++{ ++ struct xenfb *xenfb; ++ extern int domid; ++ int fd; ++ ++ /* Prepare PVFB state */ ++ xenfb = xenfb_new(); ++ if (xenfb == NULL) { ++ fprintf(stderr, "Could not create framebuffer (%s)\n", ++ strerror(errno)); ++ exit(1); ++ } ++ ++ /* Talk to the guest */ ++ if (xenfb_attach_dom(xenfb, domid) < 0) { ++ fprintf(stderr, "Could not connect to domain (%s)\n", ++ strerror(errno)); ++ exit(1); ++ } ++ xenfb->update = xen_pvfb_guest_copy; ++ xenfb->user_data = ds; ++ ++ /* Tell QEMU to allocate a graphical console */ ++ graphic_console_init(ds, ++ xen_pvfb_update, ++ xen_pvfb_invalidate, ++ xen_pvfb_screen_dump, ++ xenfb); ++ ++ /* Register our keyboard & mouse handlers */ ++ qemu_add_kbd_event_handler(xen_pvfb_put_keycode, xenfb); ++ qemu_add_mouse_event_handler(xen_pvfb_mouse_event, xenfb, ++ xenfb->abs_pointer_wanted ++ ); ++ ++ /* Listen for events from xenstore */ ++ fd = xenfb_get_store_fd(xenfb); ++ if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_store, NULL, xenfb) < 0) { ++ fprintf(stderr, "Could not register event handler (%s)\n", ++ strerror(errno)); ++ } ++ ++ /* Listen for events from the event channel */ ++ fd = xenfb_get_channel_fd(xenfb); ++ if (qemu_set_fd_handler2(fd, NULL, xen_pvfb_dispatch_channel, NULL, xenfb) < 0) { ++ fprintf(stderr, "Could not register event handler (%s)\n", ++ strerror(errno)); ++ } ++ ++ /* Setup QEMU display */ ++ dpy_resize(ds, xenfb->width, xenfb->height); ++} ++ ++QEMUMachine xenpv_machine = { ++ "xenpv", ++ "Xen Para-virtualized PC", ++ xen_init_pv, ++}; ++ ++/* ++ * Local variables: ++ * indent-tabs-mode: nil ++ * c-indent-level: 4 ++ * c-basic-offset: 4 ++ * tab-width: 4 ++ * End: ++ */ +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 10:52:07.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/Makefile.target 2007-08-23 10:52:15.000000000 -0400 +@@ -370,6 +370,8 @@ VL_OBJS+= piix4acpi.o + 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+= tpm_tis.o + DEFINES += -DHAS_AUDIO + endif +diff -rupN xen-3.1.0-src.orig/tools/ioemu/target-i386-dm/helper2.c xen-3.1.0-src.new/tools/ioemu/target-i386-dm/helper2.c +--- xen-3.1.0-src.orig/tools/ioemu/target-i386-dm/helper2.c 2007-08-23 10:41:10.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/target-i386-dm/helper2.c 2007-08-23 10:52:15.000000000 -0400 +@@ -614,14 +614,15 @@ int main_loop(void) + extern int shutdown_requested; + extern int suspend_requested; + CPUState *env = cpu_single_env; +- int evtchn_fd = xc_evtchn_fd(xce_handle); ++ int evtchn_fd = xce_handle == -1 ? -1 : xc_evtchn_fd(xce_handle); + char qemu_file[PATH_MAX]; + + buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io, + cpu_single_env); + qemu_mod_timer(buffered_io_timer, qemu_get_clock(rt_clock)); + +- qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); ++ if (evtchn_fd != -1) ++ qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); + + while (!(vm_running && suspend_requested)) + /* Wait up to 10 msec. */ +diff -rupN xen-3.1.0-src.orig/tools/ioemu/vl.c xen-3.1.0-src.new/tools/ioemu/vl.c +--- xen-3.1.0-src.orig/tools/ioemu/vl.c 2007-08-23 10:52:07.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.c 2007-08-23 10:53:46.000000000 -0400 +@@ -168,7 +168,7 @@ int xc_handle; + + time_t timeoffset = 0; + +-char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'}; ++char domain_name[1024] = "Xen-no-name"; + extern int domid; + + char vncpasswd[64]; +@@ -5698,6 +5698,7 @@ void register_machines(void) + qemu_register_machine(&isapc_machine); + #else + qemu_register_machine(&xenfv_machine); ++ qemu_register_machine(&xenpv_machine); + #endif + #elif defined(TARGET_PPC) + qemu_register_machine(&heathrow_machine); +@@ -6398,7 +6399,8 @@ int main(int argc, char **argv) + acpi_enabled = 0; + break; + case QEMU_OPTION_domainname: +- strncat(domain_name, optarg, sizeof(domain_name) - 20); ++ snprintf(domain_name, sizeof(domain_name), ++ "Xen-%s", optarg); + break; + case QEMU_OPTION_d: + domid = atoi(optarg); +diff -rupN xen-3.1.0-src.orig/tools/ioemu/vl.h xen-3.1.0-src.new/tools/ioemu/vl.h +--- xen-3.1.0-src.orig/tools/ioemu/vl.h 2007-08-23 10:52:07.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.h 2007-08-23 10:52:15.000000000 -0400 +@@ -968,6 +968,7 @@ extern QEMUMachine pc_machine; + extern QEMUMachine isapc_machine; + #ifdef CONFIG_DM + extern QEMUMachine xenfv_machine; ++extern QEMUMachine xenpv_machine; + #endif + extern int fd_bootchk; + +diff -rupN xen-3.1.0-src.orig/tools/python/xen/xend/server/vfbif.py xen-3.1.0-src.new/tools/python/xen/xend/server/vfbif.py +--- xen-3.1.0-src.orig/tools/python/xen/xend/server/vfbif.py 2007-08-23 10:41:10.000000000 -0400 ++++ xen-3.1.0-src.new/tools/python/xen/xend/server/vfbif.py 2007-08-23 10:54:47.000000000 -0400 +@@ -53,8 +53,10 @@ class VfbifController(DevController): + # is HVM, so qemu-dm will handle the vfb. + return + +- std_args = [ "--domid", "%d" % self.vm.getDomid(), +- "--title", self.vm.getName() ] ++ args = [ xen.util.auxbin.pathTo("qemu-dm"), ++ "-M", "xenpv", ++ "-d", "%d" % self.vm.getDomid(), ++ "-domain-name", self.vm.getName() ] + t = config.get("type", None) + if t == "vnc": + passwd = None +@@ -68,26 +70,24 @@ class VfbifController(DevController): + else: + log.debug("No VNC passwd configured for vfb access") + +- # Try to start the vnc backend +- args = [xen.util.auxbin.pathTo("xen-vncfb")] +- if config.has_key("vncunused"): +- args += ["--unused"] +- elif config.has_key("vncdisplay"): +- args += ["--vncport", "%d" % (5900 + int(config["vncdisplay"]))] +- vnclisten = config.get("vnclisten", ++ vnclisten = config.get('vnclisten', + xen.xend.XendOptions.instance().get_vnclisten_address()) +- args += [ "--listen", vnclisten ] ++ vncdisplay = config.get('vncdisplay', 0) ++ args += ['-vnc', "%s:%d" % (vnclisten, vncdisplay)] ++ ++ if config.get('vncunused', 0): ++ args += ['-vncunused'] ++ + if config.has_key("keymap"): + args += ["-k", "%s" % config["keymap"]] +- spawn_detached(args[0], args + std_args, os.environ) ++ spawn_detached(args[0], args, os.environ) + elif t == "sdl": +- args = [xen.util.auxbin.pathTo("xen-sdlfb")] + env = dict(os.environ) + if config.has_key("display"): + env['DISPLAY'] = config["display"] + if config.has_key("xauthority"): + env['XAUTHORITY'] = config["xauthority"] +- spawn_detached(args[0], args + std_args, env) ++ spawn_detached(args[0], args, env) + else: + raise VmError('Unknown vfb type %s (%s)' % (t, repr(config))) + +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-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/xenfb/xenfb.c 2007-08-23 10:52:15.000000000 -0400 +@@ -677,37 +677,58 @@ static int xenfb_on_state_change(struct + 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) ++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; + +- if (FD_ISSET(xc_evtchn_fd(xenfb->evt_xch), readfds)) { +- 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); ++ 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; ++} + +- if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1) +- return -1; ++ ++/* 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)) { +- 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; ++ if ((ret = xenfb_dispatch_store(xenfb_pub)) < 0) ++ return ret; + } + + return 0; +@@ -724,6 +745,18 @@ int xenfb_select_fds(struct xenfb *xenfb + 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) + { +@@ -784,3 +817,10 @@ int xenfb_send_position(struct xenfb *xe + + 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-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/xenfb/xenfb.h 2007-08-23 10:52:15.000000000 -0400 +@@ -25,8 +25,12 @@ 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); diff --git a/xen-pvfb-03-xenfb-remove.patch b/xen-pvfb-03-xenfb-remove.patch new file mode 100644 index 0000000..2ba8f52 --- /dev/null +++ b/xen-pvfb-03-xenfb-remove.patch @@ -0,0 +1,2682 @@ +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 ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++#include ++ ++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 + + /* 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +-#include +- +-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 --git a/xen-qemu-iohandler-delete.patch b/xen-qemu-iohandler-delete.patch new file mode 100644 index 0000000..af4b860 --- /dev/null +++ b/xen-qemu-iohandler-delete.patch @@ -0,0 +1,18 @@ +diff -rup xen-3.1.0-src.orig/tools/ioemu/vl.c xen-3.1.0-src.new/tools/ioemu/vl.c +--- xen-3.1.0-src.orig/tools/ioemu/vl.c 2007-08-28 16:43:11.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.c 2007-08-28 16:43:50.000000000 -0400 +@@ -5217,12 +5217,10 @@ void main_loop_wait(int timeout) + IOHandlerRecord **pioh; + + for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { +- if (ioh->deleted) +- continue; +- if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { ++ if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { + ioh->fd_read(ioh->opaque); + } +- if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { ++ if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { + ioh->fd_write(ioh->opaque); + } + } diff --git a/xen-qemu-vnc-authentication.patch b/xen-qemu-vnc-authentication.patch new file mode 100644 index 0000000..36660ce --- /dev/null +++ b/xen-qemu-vnc-authentication.patch @@ -0,0 +1,1972 @@ +diff -rupN xen-3.1.0-src.orig/tools/ioemu/configure xen-3.1.0-src.new/tools/ioemu/configure +--- xen-3.1.0-src.orig/tools/ioemu/configure 2007-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/configure 2007-08-28 17:10:41.000000000 -0400 +@@ -85,6 +85,7 @@ alsa="no" + fmod="no" + fmod_lib="" + fmod_inc="" ++vnc_tls="yes" + bsd="no" + linux="no" + kqemu="no" +@@ -214,6 +215,8 @@ for opt do + ;; + --fmod-inc=*) fmod_inc="$optarg" + ;; ++ --disable-vnc-tls) vnc_tls="no" ++ ;; + --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no" + ;; + --disable-slirp) slirp="no" +@@ -283,6 +286,7 @@ echo " --enable-coreaudio enable + echo " --enable-alsa enable ALSA audio driver" + echo " --enable-fmod enable FMOD audio driver" + echo " --enabled-dsound enable DirectSound audio driver" ++echo " --disable-vnc-tls disable TLS encryption for VNC server" + echo " --enable-system enable all system emulation targets" + echo " --disable-system disable all system emulation targets" + echo " --enable-user enable all linux usermode emulation targets" +@@ -361,6 +365,18 @@ if test "$solaris" = "yes" ; then + fi + fi + ++########################################## ++ ++# VNC TLS detection ++if test "$vnc_tls" = "yes" ; then ++ `pkg-config gnutls` || vnc_tls="no" ++fi ++if test "$vnc_tls" = "yes" ; then ++ vnc_tls_cflags=`pkg-config --cflags gnutls` ++ vnc_tls_libs=`pkg-config --libs gnutls` ++fi ++ ++########################################## + + if test -z "$target_list" ; then + # these targets are portable +@@ -707,6 +723,12 @@ if test "$fmod" = "yes" ; then + echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak + echo "#define CONFIG_FMOD 1" >> $config_h + fi ++if test "$vnc_tls" = "yes" ; then ++ echo "CONFIG_VNC_TLS=yes" >> $config_mak ++ echo "CONFIG_VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_mak ++ echo "CONFIG_VNC_TLS_LIBS=$vnc_tls_libs" >> $config_mak ++ echo "#define CONFIG_VNC_TLS 1" >> $config_h ++fi + qemu_version=`head $source_path/VERSION` + echo "VERSION=$qemu_version" >>$config_mak + echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h +@@ -914,4 +936,10 @@ if test "$source_path_used" = "yes" ; th + done + fi + ++echo "VNC TLS support $vnc_tls" ++if test "$vnc_tls" = "yes" ; then ++ echo " TLS CFLAGS $vnc_tls_cflags" ++ echo " TLS LIBS $vnc_tls_libs" ++fi ++ + rm -f $TMPO $TMPC $TMPE $TMPS +diff -rupN xen-3.1.0-src.orig/tools/ioemu/d3des.c xen-3.1.0-src.new/tools/ioemu/d3des.c +--- xen-3.1.0-src.orig/tools/ioemu/d3des.c 1969-12-31 19:00:00.000000000 -0500 ++++ xen-3.1.0-src.new/tools/ioemu/d3des.c 2007-08-28 17:10:41.000000000 -0400 +@@ -0,0 +1,434 @@ ++/* ++ * This is D3DES (V5.09) by Richard Outerbridge with the double and ++ * triple-length support removed for use in VNC. Also the bytebit[] array ++ * has been reversed so that the most significant bit in each byte of the ++ * key is ignored, not the least significant. ++ * ++ * These changes are: ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ */ ++ ++/* D3DES (V5.09) - ++ * ++ * A portable, public domain, version of the Data Encryption Standard. ++ * ++ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. ++ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation ++ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis ++ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, ++ * for humouring me on. ++ * ++ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. ++ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. ++ */ ++ ++#include "d3des.h" ++ ++static void scrunch(unsigned char *, unsigned long *); ++static void unscrun(unsigned long *, unsigned char *); ++static void desfunc(unsigned long *, unsigned long *); ++static void cookey(unsigned long *); ++ ++static unsigned long KnL[32] = { 0L }; ++ ++static unsigned short bytebit[8] = { ++ 01, 02, 04, 010, 020, 040, 0100, 0200 }; ++ ++static unsigned long bigbyte[24] = { ++ 0x800000L, 0x400000L, 0x200000L, 0x100000L, ++ 0x80000L, 0x40000L, 0x20000L, 0x10000L, ++ 0x8000L, 0x4000L, 0x2000L, 0x1000L, ++ 0x800L, 0x400L, 0x200L, 0x100L, ++ 0x80L, 0x40L, 0x20L, 0x10L, ++ 0x8L, 0x4L, 0x2L, 0x1L }; ++ ++/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ ++ ++static unsigned char pc1[56] = { ++ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, ++ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, ++ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, ++ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; ++ ++static unsigned char totrot[16] = { ++ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; ++ ++static unsigned char pc2[48] = { ++ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, ++ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, ++ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, ++ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; ++ ++void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ ++unsigned char *key; ++int edf; ++{ ++ register int i, j, l, m, n; ++ unsigned char pc1m[56], pcr[56]; ++ unsigned long kn[32]; ++ ++ for ( j = 0; j < 56; j++ ) { ++ l = pc1[j]; ++ m = l & 07; ++ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; ++ } ++ for( i = 0; i < 16; i++ ) { ++ if( edf == DE1 ) m = (15 - i) << 1; ++ else m = i << 1; ++ n = m + 1; ++ kn[m] = kn[n] = 0L; ++ for( j = 0; j < 28; j++ ) { ++ l = j + totrot[i]; ++ if( l < 28 ) pcr[j] = pc1m[l]; ++ else pcr[j] = pc1m[l - 28]; ++ } ++ for( j = 28; j < 56; j++ ) { ++ l = j + totrot[i]; ++ if( l < 56 ) pcr[j] = pc1m[l]; ++ else pcr[j] = pc1m[l - 28]; ++ } ++ for( j = 0; j < 24; j++ ) { ++ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; ++ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; ++ } ++ } ++ cookey(kn); ++ return; ++ } ++ ++static void cookey(raw1) ++register unsigned long *raw1; ++{ ++ register unsigned long *cook, *raw0; ++ unsigned long dough[32]; ++ register int i; ++ ++ cook = dough; ++ for( i = 0; i < 16; i++, raw1++ ) { ++ raw0 = raw1++; ++ *cook = (*raw0 & 0x00fc0000L) << 6; ++ *cook |= (*raw0 & 0x00000fc0L) << 10; ++ *cook |= (*raw1 & 0x00fc0000L) >> 10; ++ *cook++ |= (*raw1 & 0x00000fc0L) >> 6; ++ *cook = (*raw0 & 0x0003f000L) << 12; ++ *cook |= (*raw0 & 0x0000003fL) << 16; ++ *cook |= (*raw1 & 0x0003f000L) >> 4; ++ *cook++ |= (*raw1 & 0x0000003fL); ++ } ++ usekey(dough); ++ return; ++ } ++ ++void cpkey(into) ++register unsigned long *into; ++{ ++ register unsigned long *from, *endp; ++ ++ from = KnL, endp = &KnL[32]; ++ while( from < endp ) *into++ = *from++; ++ return; ++ } ++ ++void usekey(from) ++register unsigned long *from; ++{ ++ register unsigned long *to, *endp; ++ ++ to = KnL, endp = &KnL[32]; ++ while( to < endp ) *to++ = *from++; ++ return; ++ } ++ ++void des(inblock, outblock) ++unsigned char *inblock, *outblock; ++{ ++ unsigned long work[2]; ++ ++ scrunch(inblock, work); ++ desfunc(work, KnL); ++ unscrun(work, outblock); ++ return; ++ } ++ ++static void scrunch(outof, into) ++register unsigned char *outof; ++register unsigned long *into; ++{ ++ *into = (*outof++ & 0xffL) << 24; ++ *into |= (*outof++ & 0xffL) << 16; ++ *into |= (*outof++ & 0xffL) << 8; ++ *into++ |= (*outof++ & 0xffL); ++ *into = (*outof++ & 0xffL) << 24; ++ *into |= (*outof++ & 0xffL) << 16; ++ *into |= (*outof++ & 0xffL) << 8; ++ *into |= (*outof & 0xffL); ++ return; ++ } ++ ++static void unscrun(outof, into) ++register unsigned long *outof; ++register unsigned char *into; ++{ ++ *into++ = (unsigned char)((*outof >> 24) & 0xffL); ++ *into++ = (unsigned char)((*outof >> 16) & 0xffL); ++ *into++ = (unsigned char)((*outof >> 8) & 0xffL); ++ *into++ = (unsigned char)(*outof++ & 0xffL); ++ *into++ = (unsigned char)((*outof >> 24) & 0xffL); ++ *into++ = (unsigned char)((*outof >> 16) & 0xffL); ++ *into++ = (unsigned char)((*outof >> 8) & 0xffL); ++ *into = (unsigned char)(*outof & 0xffL); ++ return; ++ } ++ ++static unsigned long SP1[64] = { ++ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, ++ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, ++ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, ++ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, ++ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, ++ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, ++ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, ++ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, ++ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, ++ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, ++ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, ++ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, ++ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, ++ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, ++ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, ++ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; ++ ++static unsigned long SP2[64] = { ++ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, ++ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, ++ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, ++ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, ++ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, ++ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, ++ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, ++ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, ++ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, ++ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, ++ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, ++ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, ++ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, ++ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, ++ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, ++ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; ++ ++static unsigned long SP3[64] = { ++ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, ++ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, ++ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, ++ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, ++ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, ++ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, ++ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, ++ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, ++ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, ++ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, ++ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, ++ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, ++ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, ++ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, ++ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, ++ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; ++ ++static unsigned long SP4[64] = { ++ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, ++ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, ++ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, ++ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, ++ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, ++ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, ++ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, ++ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, ++ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, ++ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, ++ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, ++ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, ++ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, ++ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, ++ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, ++ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; ++ ++static unsigned long SP5[64] = { ++ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, ++ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, ++ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, ++ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, ++ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, ++ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, ++ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, ++ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, ++ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, ++ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, ++ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, ++ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, ++ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, ++ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, ++ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, ++ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; ++ ++static unsigned long SP6[64] = { ++ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, ++ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, ++ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, ++ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, ++ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, ++ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, ++ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, ++ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, ++ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, ++ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, ++ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, ++ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, ++ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, ++ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, ++ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, ++ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; ++ ++static unsigned long SP7[64] = { ++ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, ++ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, ++ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, ++ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, ++ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, ++ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, ++ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, ++ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, ++ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, ++ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, ++ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, ++ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, ++ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, ++ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, ++ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, ++ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; ++ ++static unsigned long SP8[64] = { ++ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, ++ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, ++ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, ++ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, ++ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, ++ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, ++ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, ++ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, ++ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, ++ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, ++ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, ++ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, ++ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, ++ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, ++ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, ++ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; ++ ++static void desfunc(block, keys) ++register unsigned long *block, *keys; ++{ ++ register unsigned long fval, work, right, leftt; ++ register int round; ++ ++ leftt = block[0]; ++ right = block[1]; ++ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; ++ right ^= work; ++ leftt ^= (work << 4); ++ work = ((leftt >> 16) ^ right) & 0x0000ffffL; ++ right ^= work; ++ leftt ^= (work << 16); ++ work = ((right >> 2) ^ leftt) & 0x33333333L; ++ leftt ^= work; ++ right ^= (work << 2); ++ work = ((right >> 8) ^ leftt) & 0x00ff00ffL; ++ leftt ^= work; ++ right ^= (work << 8); ++ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; ++ work = (leftt ^ right) & 0xaaaaaaaaL; ++ leftt ^= work; ++ right ^= work; ++ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; ++ ++ for( round = 0; round < 8; round++ ) { ++ work = (right << 28) | (right >> 4); ++ work ^= *keys++; ++ fval = SP7[ work & 0x3fL]; ++ fval |= SP5[(work >> 8) & 0x3fL]; ++ fval |= SP3[(work >> 16) & 0x3fL]; ++ fval |= SP1[(work >> 24) & 0x3fL]; ++ work = right ^ *keys++; ++ fval |= SP8[ work & 0x3fL]; ++ fval |= SP6[(work >> 8) & 0x3fL]; ++ fval |= SP4[(work >> 16) & 0x3fL]; ++ fval |= SP2[(work >> 24) & 0x3fL]; ++ leftt ^= fval; ++ work = (leftt << 28) | (leftt >> 4); ++ work ^= *keys++; ++ fval = SP7[ work & 0x3fL]; ++ fval |= SP5[(work >> 8) & 0x3fL]; ++ fval |= SP3[(work >> 16) & 0x3fL]; ++ fval |= SP1[(work >> 24) & 0x3fL]; ++ work = leftt ^ *keys++; ++ fval |= SP8[ work & 0x3fL]; ++ fval |= SP6[(work >> 8) & 0x3fL]; ++ fval |= SP4[(work >> 16) & 0x3fL]; ++ fval |= SP2[(work >> 24) & 0x3fL]; ++ right ^= fval; ++ } ++ ++ right = (right << 31) | (right >> 1); ++ work = (leftt ^ right) & 0xaaaaaaaaL; ++ leftt ^= work; ++ right ^= work; ++ leftt = (leftt << 31) | (leftt >> 1); ++ work = ((leftt >> 8) ^ right) & 0x00ff00ffL; ++ right ^= work; ++ leftt ^= (work << 8); ++ work = ((leftt >> 2) ^ right) & 0x33333333L; ++ right ^= work; ++ leftt ^= (work << 2); ++ work = ((right >> 16) ^ leftt) & 0x0000ffffL; ++ leftt ^= work; ++ right ^= (work << 16); ++ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; ++ leftt ^= work; ++ right ^= (work << 4); ++ *block++ = right; ++ *block = leftt; ++ return; ++ } ++ ++/* Validation sets: ++ * ++ * Single-length key, single-length plaintext - ++ * Key : 0123 4567 89ab cdef ++ * Plain : 0123 4567 89ab cde7 ++ * Cipher : c957 4425 6a5e d31d ++ * ++ * Double-length key, single-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 ++ * Plain : 0123 4567 89ab cde7 ++ * Cipher : 7f1d 0a77 826b 8aff ++ * ++ * Double-length key, double-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 ++ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff ++ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 ++ * ++ * Triple-length key, single-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 ++ * Plain : 0123 4567 89ab cde7 ++ * Cipher : de0b 7c06 ae5e 0ed5 ++ * ++ * Triple-length key, double-length plaintext - ++ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 ++ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff ++ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 ++ * ++ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery ++ **********************************************************************/ +diff -rupN xen-3.1.0-src.orig/tools/ioemu/d3des.h xen-3.1.0-src.new/tools/ioemu/d3des.h +--- xen-3.1.0-src.orig/tools/ioemu/d3des.h 1969-12-31 19:00:00.000000000 -0500 ++++ xen-3.1.0-src.new/tools/ioemu/d3des.h 2007-08-28 17:10:41.000000000 -0400 +@@ -0,0 +1,51 @@ ++/* ++ * This is D3DES (V5.09) by Richard Outerbridge with the double and ++ * triple-length support removed for use in VNC. ++ * ++ * These changes are: ++ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ++ */ ++ ++/* d3des.h - ++ * ++ * Headers and defines for d3des.c ++ * Graven Imagery, 1992. ++ * ++ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge ++ * (GEnie : OUTER; CIS : [71755,204]) ++ */ ++ ++#define EN0 0 /* MODE == encrypt */ ++#define DE1 1 /* MODE == decrypt */ ++ ++extern void deskey(unsigned char *, int); ++/* hexkey[8] MODE ++ * Sets the internal key register according to the hexadecimal ++ * key contained in the 8 bytes of hexkey, according to the DES, ++ * for encryption or decryption according to MODE. ++ */ ++ ++extern void usekey(unsigned long *); ++/* cookedkey[32] ++ * Loads the internal key register with the data in cookedkey. ++ */ ++ ++extern void cpkey(unsigned long *); ++/* cookedkey[32] ++ * Copies the contents of the internal key register into the storage ++ * located at &cookedkey[0]. ++ */ ++ ++extern void des(unsigned char *, unsigned char *); ++/* from[8] to[8] ++ * Encrypts/Decrypts (according to the key currently loaded in the ++ * internal key register) one block of eight bytes at address 'from' ++ * into the block at address 'to'. They can be the same. ++ */ ++ ++/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery ++ ********************************************************************/ +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-28 17:02:25.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/Makefile.target 2007-08-28 17:10:41.000000000 -0400 +@@ -347,6 +347,11 @@ SOUND_HW += fmopl.o adlib.o + endif + AUDIODRV+= wavcapture.o + ++ifdef CONFIG_VNC_TLS ++CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS) ++LIBS += $(CONFIG_VNC_TLS_LIBS) ++endif ++ + # SCSI layer + VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o + +@@ -410,7 +415,7 @@ endif + ifdef CONFIG_SDL + VL_OBJS+=sdl.o + endif +-VL_OBJS+=vnc.o ++VL_OBJS+=vnc.o d3des.o + ifdef CONFIG_COCOA + VL_OBJS+=cocoa.o + COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit +@@ -468,7 +473,7 @@ cocoa.o: cocoa.m + sdl.o: sdl.c keymaps.c sdl_keysym.h + $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< + +-vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h ++vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< + + sdlaudio.o: sdlaudio.c +diff -rupN xen-3.1.0-src.orig/tools/ioemu/monitor.c xen-3.1.0-src.new/tools/ioemu/monitor.c +--- xen-3.1.0-src.orig/tools/ioemu/monitor.c 2007-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/monitor.c 2007-08-28 17:10:41.000000000 -0400 +@@ -343,7 +343,7 @@ void do_eject(int force, const char *fil + eject_device(bs, force); + } + +-void do_change(const char *device, const char *filename) ++static void do_change_block(const char *device, const char *filename) + { + BlockDriverState *bs; + int i; +@@ -368,6 +368,30 @@ void do_change(const char *device, const + } + } + ++static void do_change_vnc(const char *target) ++{ ++ if (strcmp(target, "passwd") == 0 || ++ strcmp(target, "password") == 0) { ++ char password[9]; ++ monitor_readline("Password: ", 1, password, sizeof(password)-1); ++ password[sizeof(password)-1] = '\0'; ++ if (vnc_display_password(NULL, password) < 0) ++ term_printf("could not set VNC server password\n"); ++ } else { ++ if (vnc_display_open(NULL, target, 0) < 0) ++ term_printf("could not start VNC server on %s\n", target); ++ } ++} ++ ++void do_change(const char *device, const char *target) ++{ ++ if (strcmp(device, "vnc") == 0) { ++ do_change_vnc(target); ++ } else { ++ do_change_block(device, target); ++ } ++} ++ + static void do_screen_dump(const char *filename) + { + vga_hw_screen_dump(filename); +diff -rupN xen-3.1.0-src.orig/tools/ioemu/qemu_socket.h xen-3.1.0-src.new/tools/ioemu/qemu_socket.h +--- xen-3.1.0-src.orig/tools/ioemu/qemu_socket.h 2007-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/qemu_socket.h 2007-08-28 17:10:41.000000000 -0400 +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #define socket_error() errno + #define closesocket(s) close(s) +diff -rupN xen-3.1.0-src.orig/tools/ioemu/vl.c xen-3.1.0-src.new/tools/ioemu/vl.c +--- xen-3.1.0-src.orig/tools/ioemu/vl.c 2007-08-28 17:02:25.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.c 2007-08-28 17:10:41.000000000 -0400 +@@ -122,7 +122,6 @@ static DisplayState display_state; + int nographic; + int vncviewer; + int vncunused; +-struct sockaddr_in vnclisten_addr; + const char* keyboard_layout = NULL; + int64_t ticks_per_sec; + char *boot_device = NULL; +@@ -151,7 +150,7 @@ int win2k_install_hack = 0; + int usb_enabled = 0; + static VLANState *first_vlan; + int smp_cpus = 1; +-int vnc_display = -1; ++const char *vnc_display; + #if defined(TARGET_SPARC) + #define MAX_CPUS 16 + #elif defined(TARGET_I386) +@@ -5545,7 +5544,6 @@ enum { + QEMU_OPTION_acpi, + QEMU_OPTION_vncviewer, + QEMU_OPTION_vncunused, +- QEMU_OPTION_vnclisten, + }; + + typedef struct QEMUOption { +@@ -5624,7 +5622,6 @@ const QEMUOption qemu_options[] = { + { "vnc", HAS_ARG, QEMU_OPTION_vnc }, + { "vncviewer", 0, QEMU_OPTION_vncviewer }, + { "vncunused", 0, QEMU_OPTION_vncunused }, +- { "vnclisten", HAS_ARG, QEMU_OPTION_vnclisten }, + + /* temporary options */ + { "usb", 0, QEMU_OPTION_usb }, +@@ -6031,8 +6028,6 @@ int main(int argc, char **argv) + nb_nics = 0; + /* default mac address of the first network interface */ + +- memset(&vnclisten_addr.sin_addr, 0, sizeof(vnclisten_addr.sin_addr)); +- + /* init debug */ + sprintf(qemu_dm_logfilename, "/var/log/xen/qemu-dm.%ld.log", (long)getpid()); + cpu_set_log_filename(qemu_dm_logfilename); +@@ -6383,11 +6378,7 @@ int main(int argc, char **argv) + } + break; + case QEMU_OPTION_vnc: +- vnc_display = atoi(optarg); +- if (vnc_display < 0) { +- fprintf(stderr, "Invalid VNC display\n"); +- exit(1); +- } ++ vnc_display = optarg; + break; + case QEMU_OPTION_no_acpi: + acpi_enabled = 0; +@@ -6415,11 +6406,8 @@ int main(int argc, char **argv) + break; + case QEMU_OPTION_vncunused: + vncunused++; +- if (vnc_display == -1) +- vnc_display = 0; +- break; +- case QEMU_OPTION_vnclisten: +- parse_host(&vnclisten_addr, optarg); ++ if (vnc_display == NULL) ++ vnc_display = ":0"; + break; + } + } +@@ -6550,11 +6538,18 @@ int main(int argc, char **argv) + /* terminal init */ + if (nographic) { + dumb_display_init(ds); +- } else if (vnc_display != -1) { +- vnc_display = vnc_display_init(ds, vnc_display, vncunused, &vnclisten_addr); ++ } else if (vnc_display != NULL) { ++ int vnc_port; ++ char password[20]; ++ vnc_display_init(ds); ++ if (xenstore_read_vncpasswd(domid, password, sizeof(password)) < 0) ++ exit(0); ++ vnc_display_password(ds, password); ++ if ((vnc_port = vnc_display_open(ds, vnc_display, vncunused)) < 0) ++ exit (0); + if (vncviewer) +- vnc_start_viewer(vnc_display); +- xenstore_write_vncport(vnc_display); ++ vnc_start_viewer(vnc_port); ++ xenstore_write_vncport(vnc_port); + } else { + #if defined(CONFIG_SDL) + sdl_display_init(ds, full_screen); +@@ -6626,7 +6621,7 @@ int main(int argc, char **argv) + } + } + +- if (vnc_display == -1) { ++ if (vnc_display == NULL) { + gui_timer = qemu_new_timer(rt_clock, gui_update, NULL); + qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock)); + } +diff -rupN xen-3.1.0-src.orig/tools/ioemu/vl.h xen-3.1.0-src.new/tools/ioemu/vl.h +--- xen-3.1.0-src.orig/tools/ioemu/vl.h 2007-08-28 17:02:25.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.h 2007-08-28 17:10:41.000000000 -0400 +@@ -813,7 +813,10 @@ void sdl_display_init(DisplayState *ds, + void cocoa_display_init(DisplayState *ds, int full_screen); + + /* vnc.c */ +-int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sockaddr_in *addr); ++void vnc_display_init(DisplayState *ds); ++void vnc_display_close(DisplayState *ds); ++int vnc_display_open(DisplayState *ds, const char * display, int find_unused); ++int vnc_display_password(DisplayState *ds, const char *password); + int vnc_start_viewer(int port); + + /* ide.c */ +diff -rupN xen-3.1.0-src.orig/tools/ioemu/vnc.c xen-3.1.0-src.new/tools/ioemu/vnc.c +--- xen-3.1.0-src.orig/tools/ioemu/vnc.c 2007-08-28 17:02:25.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vnc.c 2007-08-28 17:10:41.000000000 -0400 +@@ -44,6 +44,28 @@ + + #include "vnc_keysym.h" + #include "keymaps.c" ++#include "d3des.h" ++ ++#if CONFIG_VNC_TLS ++#include ++#include ++#endif /* CONFIG_VNC_TLS */ ++ ++// #define _VNC_DEBUG 1 ++ ++#if _VNC_DEBUG ++#define VNC_DEBUG(fmt, ...) do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) ++ ++#if CONFIG_VNC_TLS && _VNC_DEBUG >= 2 ++/* Very verbose, so only enabled for _VNC_DEBUG >= 2 */ ++static void vnc_debug_gnutls_log(int level, const char* str) { ++ VNC_DEBUG("%d %s", level, str); ++} ++#endif /* CONFIG_VNC_TLS && _VNC_DEBUG */ ++#else ++#define VNC_DEBUG(fmt, ...) do { } while (0) ++#endif ++ + + #define XK_MISCELLANY + #define XK_LATIN1 +@@ -74,6 +96,45 @@ typedef void VncSendHextileTile(VncState + #define VNC_DIRTY_WORDS (VNC_MAX_WIDTH / (16 * 32)) + #endif + ++#define VNC_AUTH_CHALLENGE_SIZE 16 ++ ++enum { ++ VNC_AUTH_INVALID = 0, ++ VNC_AUTH_NONE = 1, ++ VNC_AUTH_VNC = 2, ++ VNC_AUTH_RA2 = 5, ++ VNC_AUTH_RA2NE = 6, ++ VNC_AUTH_TIGHT = 16, ++ VNC_AUTH_ULTRA = 17, ++ VNC_AUTH_TLS = 18, ++ VNC_AUTH_VENCRYPT = 19 ++}; ++ ++#if CONFIG_VNC_TLS ++enum { ++ VNC_WIREMODE_CLEAR, ++ VNC_WIREMODE_TLS, ++}; ++ ++enum { ++ VNC_AUTH_VENCRYPT_PLAIN = 256, ++ VNC_AUTH_VENCRYPT_TLSNONE = 257, ++ VNC_AUTH_VENCRYPT_TLSVNC = 258, ++ VNC_AUTH_VENCRYPT_TLSPLAIN = 259, ++ VNC_AUTH_VENCRYPT_X509NONE = 260, ++ VNC_AUTH_VENCRYPT_X509VNC = 261, ++ VNC_AUTH_VENCRYPT_X509PLAIN = 262, ++}; ++ ++#if CONFIG_VNC_TLS ++#define X509_CA_CERT_FILE "ca-cert.pem" ++#define X509_CA_CRL_FILE "ca-crl.pem" ++#define X509_SERVER_KEY_FILE "server-key.pem" ++#define X509_SERVER_CERT_FILE "server-cert.pem" ++#endif ++ ++#endif /* CONFIG_VNC_TLS */ ++ + struct VncState + { + QEMUTimer *timer; +@@ -93,6 +154,24 @@ struct VncState + int depth; /* internal VNC frame buffer byte per pixel */ + int has_resize; + int has_hextile; ++ ++ int major; ++ int minor; ++ ++ char *display; ++ char *password; ++ int auth; ++#if CONFIG_VNC_TLS ++ int subauth; ++ int x509verify; ++#endif ++ char challenge[VNC_AUTH_CHALLENGE_SIZE]; ++ ++#if CONFIG_VNC_TLS ++ int wiremode; ++ gnutls_session_t tls_session; ++#endif ++ + Buffer output; + Buffer input; + kbd_layout_t *kbd_layout; +@@ -117,6 +196,8 @@ struct VncState + int numlock; + }; + ++static VncState *vnc_state; /* needed for info vnc */ ++ + #define DIRTY_PIXEL_BITS 64 + #define X2DP_DOWN(vs, x) ((x) >> (vs)->dirty_pixel_shift) + #define X2DP_UP(vs, x) \ +@@ -672,11 +753,19 @@ static int vnc_client_io_error(VncState + if (ret == -1 && (last_errno == EINTR || last_errno == EAGAIN)) + return 0; + ++ VNC_DEBUG("Closing down client sock %d %d\n", ret, ret < 0 ? last_errno : 0); + qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); + closesocket(vs->csock); + vs->csock = -1; + buffer_reset(&vs->input); + buffer_reset(&vs->output); ++#if CONFIG_VNC_TLS ++ if (vs->tls_session) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ } ++ vs->wiremode = VNC_WIREMODE_CLEAR; ++#endif /* CONFIG_VNC_TLS */ + return 0; + } + return ret; +@@ -692,7 +781,19 @@ static void vnc_client_write(void *opaqu + long ret; + VncState *vs = opaque; + +- ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0); ++#if CONFIG_VNC_TLS ++ if (vs->tls_session) { ++ ret = gnutls_write(vs->tls_session, vs->output.buffer, vs->output.offset); ++ if (ret < 0) { ++ if (ret == GNUTLS_E_AGAIN) ++ errno = EAGAIN; ++ else ++ errno = EIO; ++ ret = -1; ++ } ++ } else ++#endif /* CONFIG_VNC_TLS */ ++ ret = send(vs->csock, vs->output.buffer, vs->output.offset, 0); + ret = vnc_client_io_error(vs, ret, socket_error()); + if (!ret) + return; +@@ -718,7 +819,19 @@ static void vnc_client_read(void *opaque + + buffer_reserve(&vs->input, 4096); + +- ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0); ++#if CONFIG_VNC_TLS ++ if (vs->tls_session) { ++ ret = gnutls_read(vs->tls_session, buffer_end(&vs->input), 4096); ++ if (ret < 0) { ++ if (ret == GNUTLS_E_AGAIN) ++ errno = EAGAIN; ++ else ++ errno = EIO; ++ ret = -1; ++ } ++ } else ++#endif /* CONFIG_VNC_TLS */ ++ ret = recv(vs->csock, buffer_end(&vs->input), 4096, 0); + ret = vnc_client_io_error(vs, ret, socket_error()); + if (!ret) + return; +@@ -815,6 +928,41 @@ static uint32_t read_u32(uint8_t *data, + (data[offset + 2] << 8) | data[offset + 3]); + } + ++#if CONFIG_VNC_TLS ++ssize_t vnc_tls_push(gnutls_transport_ptr_t transport, ++ const void *data, ++ size_t len) { ++ struct VncState *vs = (struct VncState *)transport; ++ int ret; ++ ++ retry: ++ ret = send(vs->csock, data, len, 0); ++ if (ret < 0) { ++ if (errno == EINTR) ++ goto retry; ++ return -1; ++ } ++ return ret; ++} ++ ++ ++ssize_t vnc_tls_pull(gnutls_transport_ptr_t transport, ++ void *data, ++ size_t len) { ++ struct VncState *vs = (struct VncState *)transport; ++ int ret; ++ ++ retry: ++ ret = recv(vs->csock, data, len, 0); ++ if (ret < 0) { ++ if (errno == EINTR) ++ goto retry; ++ return -1; ++ } ++ return ret; ++} ++#endif /* CONFIG_VNC_TLS */ ++ + static void client_cut_text(VncState *vs, size_t len, char *text) + { + } +@@ -1257,23 +1405,575 @@ static int protocol_client_init(VncState + } + + +-static int protocol_version(VncState *vs, uint8_t *version, size_t len) ++static void make_challenge(VncState *vs) ++{ ++ int i; ++ ++ srand(time(NULL)+getpid()+getpid()*987654+rand()); ++ ++ for (i = 0 ; i < sizeof(vs->challenge) ; i++) ++ vs->challenge[i] = (int) (256.0*rand()/(RAND_MAX+1.0)); ++} ++ ++static int protocol_client_auth_vnc(VncState *vs, char *data, size_t len) ++{ ++ char response[VNC_AUTH_CHALLENGE_SIZE]; ++ int i, j, pwlen; ++ char key[8]; ++ ++ if (!vs->password || !vs->password[0]) { ++ VNC_DEBUG("No password configured on server"); ++ vnc_write_u32(vs, 1); /* Reject auth */ ++ if (vs->minor >= 8) { ++ static const char err[] = "Authentication failed"; ++ vnc_write_u32(vs, sizeof(err)); ++ vnc_write(vs, err, sizeof(err)); ++ } ++ vnc_flush(vs); ++ vnc_client_error(vs); ++ return 0; ++ } ++ ++ memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE); ++ ++ /* Calculate the expected challenge response */ ++ pwlen = strlen(vs->password); ++ for (i=0; ipassword[i] : 0; ++ deskey(key, EN0); ++ for (j = 0; j < VNC_AUTH_CHALLENGE_SIZE; j += 8) ++ des(response+j, response+j); ++ ++ /* Compare expected vs actual challenge response */ ++ if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) { ++ VNC_DEBUG("Client challenge reponse did not match\n"); ++ vnc_write_u32(vs, 1); /* Reject auth */ ++ if (vs->minor >= 8) { ++ static const char err[] = "Authentication failed"; ++ vnc_write_u32(vs, sizeof(err)); ++ vnc_write(vs, err, sizeof(err)); ++ } ++ vnc_flush(vs); ++ vnc_client_error(vs); ++ } else { ++ VNC_DEBUG("Accepting VNC challenge response\n"); ++ vnc_write_u32(vs, 0); /* Accept auth */ ++ vnc_flush(vs); ++ ++ vnc_read_when(vs, protocol_client_init, 1); ++ } ++ return 0; ++} ++ ++static int start_auth_vnc(VncState *vs) ++{ ++ make_challenge(vs); ++ /* Send client a 'random' challenge */ ++ vnc_write(vs, vs->challenge, sizeof(vs->challenge)); ++ vnc_flush(vs); ++ ++ vnc_read_when(vs, protocol_client_auth_vnc, sizeof(vs->challenge)); ++ return 0; ++} ++ ++ ++#if CONFIG_VNC_TLS ++#define DH_BITS 1024 ++static gnutls_dh_params_t dh_params; ++ ++static int vnc_tls_initialize(void) ++{ ++ static int tlsinitialized = 0; ++ ++ if (tlsinitialized) ++ return 1; ++ ++ if (gnutls_global_init () < 0) ++ return 0; ++ ++ /* XXX ought to re-generate diffie-hellmen params periodically */ ++ if (gnutls_dh_params_init (&dh_params) < 0) ++ return 0; ++ if (gnutls_dh_params_generate2 (dh_params, DH_BITS) < 0) ++ return 0; ++ ++#if _VNC_DEBUG == 2 ++ gnutls_global_set_log_level(10); ++ gnutls_global_set_log_function(vnc_debug_gnutls_log); ++#endif ++ ++ tlsinitialized = 1; ++ ++ return 1; ++} ++ ++static gnutls_anon_server_credentials vnc_tls_initialize_anon_cred(void) ++{ ++ gnutls_anon_server_credentials anon_cred; ++ int ret; ++ ++ if ((ret = gnutls_anon_allocate_server_credentials(&anon_cred)) < 0) { ++ VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret)); ++ return NULL; ++ } ++ ++ gnutls_anon_set_server_dh_params(anon_cred, dh_params); ++ ++ return anon_cred; ++} ++ ++ ++static gnutls_certificate_credentials_t vnc_tls_initialize_x509_cred(void) ++{ ++ gnutls_certificate_credentials_t x509_cred; ++ int ret; ++ struct stat st; ++ ++ if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) { ++ VNC_DEBUG("Cannot allocate credentials %s\n", gnutls_strerror(ret)); ++ return NULL; ++ } ++ if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, X509_CA_CERT_FILE, GNUTLS_X509_FMT_PEM)) < 0) { ++ VNC_DEBUG("Cannot load CA certificate %s\n", gnutls_strerror(ret)); ++ gnutls_certificate_free_credentials(x509_cred); ++ return NULL; ++ } ++ ++ if ((ret = gnutls_certificate_set_x509_key_file (x509_cred, X509_SERVER_CERT_FILE, ++ X509_SERVER_KEY_FILE, ++ GNUTLS_X509_FMT_PEM)) < 0) { ++ VNC_DEBUG("Cannot load certificate & key %s\n", gnutls_strerror(ret)); ++ gnutls_certificate_free_credentials(x509_cred); ++ return NULL; ++ } ++ ++ if (stat(X509_CA_CRL_FILE, &st) < 0) { ++ if (errno != ENOENT) { ++ gnutls_certificate_free_credentials(x509_cred); ++ return NULL; ++ } ++ } else { ++ if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, X509_CA_CRL_FILE, GNUTLS_X509_FMT_PEM)) < 0) { ++ VNC_DEBUG("Cannot load CRL %s\n", gnutls_strerror(ret)); ++ gnutls_certificate_free_credentials(x509_cred); ++ return NULL; ++ } ++ } ++ ++ gnutls_certificate_set_dh_params (x509_cred, dh_params); ++ ++ return x509_cred; ++} ++ ++static int vnc_validate_certificate(struct VncState *vs) ++{ ++ int ret; ++ unsigned int status; ++ const gnutls_datum_t *certs; ++ unsigned int nCerts, i; ++ time_t now; ++ ++ VNC_DEBUG("Validating client certificate\n"); ++ if ((ret = gnutls_certificate_verify_peers2 (vs->tls_session, &status)) < 0) { ++ VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret)); ++ return -1; ++ } ++ ++ if ((now = time(NULL)) == ((time_t)-1)) { ++ return -1; ++ } ++ ++ if (status != 0) { ++ if (status & GNUTLS_CERT_INVALID) ++ VNC_DEBUG("The certificate is not trusted.\n"); ++ ++ if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) ++ VNC_DEBUG("The certificate hasn't got a known issuer.\n"); ++ ++ if (status & GNUTLS_CERT_REVOKED) ++ VNC_DEBUG("The certificate has been revoked.\n"); ++ ++ if (status & GNUTLS_CERT_INSECURE_ALGORITHM) ++ VNC_DEBUG("The certificate uses an insecure algorithm\n"); ++ ++ return -1; ++ } else { ++ VNC_DEBUG("Certificate is valid!\n"); ++ } ++ ++ /* Only support x509 for now */ ++ if (gnutls_certificate_type_get(vs->tls_session) != GNUTLS_CRT_X509) ++ return -1; ++ ++ if (!(certs = gnutls_certificate_get_peers(vs->tls_session, &nCerts))) ++ return -1; ++ ++ for (i = 0 ; i < nCerts ; i++) { ++ gnutls_x509_crt_t cert; ++ VNC_DEBUG ("Checking certificate chain %d\n", i); ++ if (gnutls_x509_crt_init (&cert) < 0) ++ return -1; ++ ++ if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) { ++ gnutls_x509_crt_deinit (cert); ++ return -1; ++ } ++ ++ if (gnutls_x509_crt_get_expiration_time (cert) < now) { ++ VNC_DEBUG("The certificate has expired\n"); ++ gnutls_x509_crt_deinit (cert); ++ return -1; ++ } ++ ++ if (gnutls_x509_crt_get_activation_time (cert) > now) { ++ VNC_DEBUG("The certificate is not yet activated\n"); ++ gnutls_x509_crt_deinit (cert); ++ return -1; ++ } ++ ++ if (gnutls_x509_crt_get_activation_time (cert) > now) { ++ VNC_DEBUG("The certificate is not yet activated\n"); ++ gnutls_x509_crt_deinit (cert); ++ return -1; ++ } ++ ++ gnutls_x509_crt_deinit (cert); ++ } ++ ++ return 0; ++} ++ ++ ++static int start_auth_vencrypt_subauth(VncState *vs) ++{ ++ switch (vs->subauth) { ++ case VNC_AUTH_VENCRYPT_TLSNONE: ++ case VNC_AUTH_VENCRYPT_X509NONE: ++ VNC_DEBUG("Accept TLS auth none\n"); ++ vnc_write_u32(vs, 0); /* Accept auth completion */ ++ vnc_read_when(vs, protocol_client_init, 1); ++ break; ++ ++ case VNC_AUTH_VENCRYPT_TLSVNC: ++ case VNC_AUTH_VENCRYPT_X509VNC: ++ VNC_DEBUG("Start TLS auth VNC\n"); ++ return start_auth_vnc(vs); ++ ++ default: /* Should not be possible, but just in case */ ++ VNC_DEBUG("Reject auth %d\n", vs->auth); ++ vnc_write_u8(vs, 1); ++ if (vs->minor >= 8) { ++ static const char err[] = "Unsupported authentication type"; ++ vnc_write_u32(vs, sizeof(err)); ++ vnc_write(vs, err, sizeof(err)); ++ } ++ vnc_client_error(vs); ++ } ++ ++ return 0; ++} ++ ++static void vnc_handshake_io(void *opaque); ++ ++static int vnc_continue_handshake(struct VncState *vs) { ++ int ret; ++ ++ if ((ret = gnutls_handshake(vs->tls_session)) < 0) { ++ if (!gnutls_error_is_fatal(ret)) { ++ VNC_DEBUG("Handshake interrupted (blocking)\n"); ++ if (!gnutls_record_get_direction(vs->tls_session)) ++ qemu_set_fd_handler(vs->csock, vnc_handshake_io, NULL, vs); ++ else ++ qemu_set_fd_handler(vs->csock, NULL, vnc_handshake_io, vs); ++ return 0; ++ } ++ VNC_DEBUG("Handshake failed %s\n", gnutls_strerror(ret)); ++ vnc_client_error(vs); ++ return -1; ++ } ++ ++ if (vs->x509verify) { ++ if (vnc_validate_certificate(vs) < 0) { ++ VNC_DEBUG("Client verification failed\n"); ++ vnc_client_error(vs); ++ return -1; ++ } else { ++ VNC_DEBUG("Client verification passed\n"); ++ } ++ } ++ ++ VNC_DEBUG("Handshake done, switching to TLS data mode\n"); ++ vs->wiremode = VNC_WIREMODE_TLS; ++ qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, vnc_client_write, vs); ++ ++ return start_auth_vencrypt_subauth(vs); ++} ++ ++static void vnc_handshake_io(void *opaque) { ++ struct VncState *vs = (struct VncState *)opaque; ++ ++ VNC_DEBUG("Handshake IO continue\n"); ++ vnc_continue_handshake(vs); ++} ++ ++#define NEED_X509_AUTH(vs) \ ++ ((vs)->subauth == VNC_AUTH_VENCRYPT_X509NONE || \ ++ (vs)->subauth == VNC_AUTH_VENCRYPT_X509VNC || \ ++ (vs)->subauth == VNC_AUTH_VENCRYPT_X509PLAIN) ++ ++ ++static int vnc_start_tls(struct VncState *vs) { ++ static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 }; ++ static const int protocol_priority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; ++ static const int kx_anon[] = {GNUTLS_KX_ANON_DH, 0}; ++ static const int kx_x509[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0}; ++ ++ VNC_DEBUG("Do TLS setup\n"); ++ if (vnc_tls_initialize() < 0) { ++ VNC_DEBUG("Failed to init TLS\n"); ++ vnc_client_error(vs); ++ return -1; ++ } ++ if (vs->tls_session == NULL) { ++ if (gnutls_init(&vs->tls_session, GNUTLS_SERVER) < 0) { ++ vnc_client_error(vs); ++ return -1; ++ } ++ ++ if (gnutls_set_default_priority(vs->tls_session) < 0) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ vnc_client_error(vs); ++ return -1; ++ } ++ ++ if (gnutls_kx_set_priority(vs->tls_session, NEED_X509_AUTH(vs) ? kx_x509 : kx_anon) < 0) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ vnc_client_error(vs); ++ return -1; ++ } ++ ++ if (gnutls_certificate_type_set_priority(vs->tls_session, cert_type_priority) < 0) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ vnc_client_error(vs); ++ return -1; ++ } ++ ++ if (gnutls_protocol_set_priority(vs->tls_session, protocol_priority) < 0) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ vnc_client_error(vs); ++ return -1; ++ } ++ ++ if (NEED_X509_AUTH(vs)) { ++ gnutls_certificate_server_credentials x509_cred = vnc_tls_initialize_x509_cred(); ++ if (!x509_cred) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ vnc_client_error(vs); ++ return -1; ++ } ++ if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_CERTIFICATE, x509_cred) < 0) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ gnutls_certificate_free_credentials(x509_cred); ++ vnc_client_error(vs); ++ return -1; ++ } ++ if (vs->x509verify) { ++ VNC_DEBUG("Requesting a client certificate\n"); ++ gnutls_certificate_server_set_request (vs->tls_session, GNUTLS_CERT_REQUEST); ++ } ++ ++ } else { ++ gnutls_anon_server_credentials anon_cred = vnc_tls_initialize_anon_cred(); ++ if (!anon_cred) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ vnc_client_error(vs); ++ return -1; ++ } ++ if (gnutls_credentials_set(vs->tls_session, GNUTLS_CRD_ANON, anon_cred) < 0) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ gnutls_anon_free_server_credentials(anon_cred); ++ vnc_client_error(vs); ++ return -1; ++ } ++ } ++ ++ gnutls_transport_set_ptr(vs->tls_session, (gnutls_transport_ptr_t)vs); ++ gnutls_transport_set_push_function(vs->tls_session, vnc_tls_push); ++ gnutls_transport_set_pull_function(vs->tls_session, vnc_tls_pull); ++ } ++ ++ VNC_DEBUG("Start TLS handshake process\n"); ++ return vnc_continue_handshake(vs); ++} ++ ++static int protocol_client_vencrypt_auth(VncState *vs, char *data, size_t len) ++{ ++ int auth = read_u32(data, 0); ++ ++ if (auth != vs->subauth) { ++ VNC_DEBUG("Rejecting auth %d\n", auth); ++ vnc_write_u8(vs, 0); /* Reject auth */ ++ vnc_flush(vs); ++ vnc_client_error(vs); ++ } else { ++ VNC_DEBUG("Accepting auth %d, starting handshake\n", auth); ++ vnc_write_u8(vs, 1); /* Accept auth */ ++ vnc_flush(vs); ++ ++ if (vnc_start_tls(vs) < 0) { ++ VNC_DEBUG("Failed to complete TLS\n"); ++ return 0; ++ } ++ ++ if (vs->wiremode == VNC_WIREMODE_TLS) { ++ VNC_DEBUG("Starting VeNCrypt subauth\n"); ++ return start_auth_vencrypt_subauth(vs); ++ } else { ++ VNC_DEBUG("TLS handshake blocked\n"); ++ return 0; ++ } ++ } ++ return 0; ++} ++ ++static int protocol_client_vencrypt_init(VncState *vs, char *data, size_t len) ++{ ++ if (data[0] != 0 || ++ data[1] != 2) { ++ VNC_DEBUG("Unsupported VeNCrypt protocol %d.%d\n", (int)data[0], (int)data[1]); ++ vnc_write_u8(vs, 1); /* Reject version */ ++ vnc_flush(vs); ++ vnc_client_error(vs); ++ } else { ++ VNC_DEBUG("Sending allowed auth %d\n", vs->subauth); ++ vnc_write_u8(vs, 0); /* Accept version */ ++ vnc_write_u8(vs, 1); /* Number of sub-auths */ ++ vnc_write_u32(vs, vs->subauth); /* The supported auth */ ++ vnc_flush(vs); ++ vnc_read_when(vs, protocol_client_vencrypt_auth, 4); ++ } ++ return 0; ++} ++ ++static int start_auth_vencrypt(VncState *vs) ++{ ++ /* Send VeNCrypt version 0.2 */ ++ vnc_write_u8(vs, 0); ++ vnc_write_u8(vs, 2); ++ ++ vnc_read_when(vs, protocol_client_vencrypt_init, 2); ++ return 0; ++} ++#endif /* CONFIG_VNC_TLS */ ++ ++static int protocol_client_auth(VncState *vs, char *data, size_t len) ++{ ++ /* We only advertise 1 auth scheme at a time, so client ++ * must pick the one we sent. Verify this */ ++ if (data[0] != vs->auth) { /* Reject auth */ ++ VNC_DEBUG("Reject auth %d\n", (int)data[0]); ++ vnc_write_u32(vs, 1); ++ if (vs->minor >= 8) { ++ static const char err[] = "Authentication failed"; ++ vnc_write_u32(vs, sizeof(err)); ++ vnc_write(vs, err, sizeof(err)); ++ } ++ vnc_client_error(vs); ++ } else { /* Accept requested auth */ ++ VNC_DEBUG("Client requested auth %d\n", (int)data[0]); ++ switch (vs->auth) { ++ case VNC_AUTH_NONE: ++ VNC_DEBUG("Accept auth none\n"); ++ vnc_write_u32(vs, 0); /* Accept auth completion */ ++ vnc_read_when(vs, protocol_client_init, 1); ++ break; ++ ++ case VNC_AUTH_VNC: ++ VNC_DEBUG("Start VNC auth\n"); ++ return start_auth_vnc(vs); ++ ++#if CONFIG_VNC_TLS ++ case VNC_AUTH_VENCRYPT: ++ VNC_DEBUG("Accept VeNCrypt auth\n");; ++ return start_auth_vencrypt(vs); ++#endif /* CONFIG_VNC_TLS */ ++ ++ default: /* Should not be possible, but just in case */ ++ VNC_DEBUG("Reject auth %d\n", vs->auth); ++ vnc_write_u8(vs, 1); ++ if (vs->minor >= 8) { ++ static const char err[] = "Authentication failed"; ++ vnc_write_u32(vs, sizeof(err)); ++ vnc_write(vs, err, sizeof(err)); ++ } ++ vnc_client_error(vs); ++ } ++ } ++ return 0; ++} ++ ++static int protocol_version(VncState *vs, char *version, size_t len) + { + char local[13]; +- int maj, min; + + memcpy(local, version, 12); + local[12] = 0; + +- if (sscanf(local, "RFB %03d.%03d\n", &maj, &min) != 2) { ++ if (sscanf(local, "RFB %03d.%03d\n", &vs->major, &vs->minor) != 2) { ++ VNC_DEBUG("Malformed protocol version %s\n", local); + vnc_client_error(vs); + return 0; + } +- +- vnc_write_u32(vs, 1); /* None */ +- vnc_flush(vs); +- +- vnc_read_when(vs, protocol_client_init, 1); ++ VNC_DEBUG("Client request protocol version %d.%d\n", vs->major, vs->minor); ++ if (vs->major != 3 || ++ (vs->minor != 3 && ++ vs->minor != 5 && ++ vs->minor != 7 && ++ vs->minor != 8)) { ++ VNC_DEBUG("Unsupported client version\n"); ++ vnc_write_u32(vs, VNC_AUTH_INVALID); ++ vnc_flush(vs); ++ vnc_client_error(vs); ++ return 0; ++ } ++ /* Some broken client report v3.5 which spec requires to be treated ++ * as equivalent to v3.3 by servers ++ */ ++ if (vs->minor == 5) ++ vs->minor = 3; ++ ++ if (vs->minor == 3) { ++ if (vs->auth == VNC_AUTH_NONE) { ++ VNC_DEBUG("Tell client auth none\n"); ++ vnc_write_u32(vs, vs->auth); ++ vnc_flush(vs); ++ vnc_read_when(vs, protocol_client_init, 1); ++ } else if (vs->auth == VNC_AUTH_VNC) { ++ VNC_DEBUG("Tell client VNC auth\n"); ++ vnc_write_u32(vs, vs->auth); ++ vnc_flush(vs); ++ start_auth_vnc(vs); ++ } else { ++ VNC_DEBUG("Unsupported auth %d for protocol 3.3\n", vs->auth); ++ vnc_write_u32(vs, VNC_AUTH_INVALID); ++ vnc_flush(vs); ++ vnc_client_error(vs); ++ } ++ } else { ++ VNC_DEBUG("Telling client we support auth %d\n", vs->auth); ++ vnc_write_u8(vs, 1); /* num auth */ ++ vnc_write_u8(vs, vs->auth); ++ vnc_read_when(vs, protocol_client_auth, 1); ++ vnc_flush(vs); ++ } + + return 0; + } +@@ -1286,9 +1986,10 @@ static void vnc_listen_read(void *opaque + + vs->csock = accept(vs->lsock, (struct sockaddr *)&addr, &addrlen); + if (vs->csock != -1) { ++ VNC_DEBUG("New client on socket %d\n", vs->csock); + socket_set_nonblock(vs->csock); + qemu_set_fd_handler2(vs->csock, NULL, vnc_client_read, NULL, opaque); +- vnc_write(vs, "RFB 003.003\n", 12); ++ vnc_write(vs, "RFB 003.008\n", 12); + vnc_flush(vs); + vnc_read_when(vs, protocol_version, 12); + framebuffer_set_updated(vs, 0, 0, vs->ds->width, vs->ds->height); +@@ -1299,9 +2000,8 @@ static void vnc_listen_read(void *opaque + } + } + +-int vnc_display_init(DisplayState *ds, int display, int find_unused, struct sockaddr_in *addr) ++void vnc_display_init(DisplayState *ds) + { +- int reuse_addr, ret; + VncState *vs; + + vs = qemu_mallocz(sizeof(VncState)); +@@ -1309,11 +2009,13 @@ int vnc_display_init(DisplayState *ds, i + exit(1); + + ds->opaque = vs; ++ vnc_state = vs; ++ vs->display = NULL; ++ vs->password = NULL; + + vs->lsock = -1; + vs->csock = -1; + vs->depth = 4; +- vs->numlock = 0; + + vs->ds = ds; + +@@ -1324,51 +2026,230 @@ int vnc_display_init(DisplayState *ds, i + if (!vs->kbd_layout) + exit(1); + +- vs->lsock = socket(PF_INET, SOCK_STREAM, 0); +- if (vs->lsock == -1) { +- fprintf(stderr, "Could not create socket\n"); +- exit(1); ++ vs->ds->data = NULL; ++ vs->ds->dpy_update = vnc_dpy_update; ++ vs->ds->dpy_resize = vnc_dpy_resize; ++ vs->ds->dpy_refresh = vnc_dpy_refresh; ++ ++ vnc_dpy_resize(vs->ds, 640, 400); ++ ++ memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row)); ++} ++ ++void vnc_display_close(DisplayState *ds) ++{ ++ VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; ++ ++ if (vs->display) { ++ qemu_free(vs->display); ++ vs->display = NULL; ++ } ++ if (vs->lsock != -1) { ++ qemu_set_fd_handler2(vs->lsock, NULL, NULL, NULL, NULL); ++ close(vs->lsock); ++ vs->lsock = -1; ++ } ++ if (vs->csock != -1) { ++ qemu_set_fd_handler2(vs->csock, NULL, NULL, NULL, NULL); ++ closesocket(vs->csock); ++ vs->csock = -1; ++ buffer_reset(&vs->input); ++ buffer_reset(&vs->output); ++#if CONFIG_VNC_TLS ++ if (vs->tls_session) { ++ gnutls_deinit(vs->tls_session); ++ vs->tls_session = NULL; ++ } ++ vs->wiremode = VNC_WIREMODE_CLEAR; ++#endif /* CONFIG_VNC_TLS */ + } ++ vs->auth = VNC_AUTH_INVALID; ++#if CONFIG_VNC_TLS ++ vs->subauth = VNC_AUTH_INVALID; ++ vs->x509verify = 0; ++#endif ++} + +- reuse_addr = 1; +- ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, +- (const char *)&reuse_addr, sizeof(reuse_addr)); +- if (ret == -1) { +- fprintf(stderr, "setsockopt() failed\n"); +- exit(1); ++int parse_host_port(struct sockaddr_in *saddr, const char *str); ++ ++ ++ ++int vnc_display_password(DisplayState *ds, const char *password) ++{ ++ VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; ++ ++ if (vs->password) { ++ qemu_free(vs->password); ++ vs->password = NULL; ++ } ++ if (password && password[0]) { ++ if (!(vs->password = qemu_strdup(password))) ++ return -1; + } + +- retry: +- addr->sin_family = AF_INET; +- addr->sin_port = htons(5900 + display); ++ return 0; ++} + +- if (bind(vs->lsock, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) == -1) { +- if (find_unused && errno == EADDRINUSE) { +- display++; +- goto retry; ++int vnc_display_open(DisplayState *ds, const char *display, int find_unused) ++{ ++ struct sockaddr *addr; ++ struct sockaddr_in iaddr; ++#ifndef _WIN32 ++ struct sockaddr_un uaddr; ++#endif ++ int reuse_addr, ret; ++ socklen_t addrlen; ++ const char *p; ++ VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; ++ const char *options; ++ int password = 0; ++#if CONFIG_VNC_TLS ++ int tls = 0, x509 = 0; ++#endif ++ ++ vnc_display_close(ds); ++ if (strcmp(display, "none") == 0) ++ return 0; ++ ++ if (!(vs->display = strdup(display))) ++ return -1; ++ ++ options = display; ++ while ((options = strchr(options, ','))) { ++ options++; ++ if (strncmp(options, "password", 8) == 0) { ++ password = 1; /* Require password auth */ ++#if CONFIG_VNC_TLS ++ } else if (strncmp(options, "tls", 3) == 0) { ++ tls = 1; /* Require TLS */ ++ } else if (strncmp(options, "x509verify", 10) == 0) { ++ x509 = 1; /* Require x509 certificates... */ ++ vs->x509verify = 1;/* ...and verify client certs */ ++ } else if (strncmp(options, "x509", 4) == 0) { ++ x509 = 1; /* Require x509 certificates */ ++#endif + } +- fprintf(stderr, "bind() failed\n"); +- exit(1); + } + +- if (listen(vs->lsock, 1) == -1) { +- fprintf(stderr, "listen() failed\n"); +- exit(1); ++ if (password) { ++#if CONFIG_VNC_TLS ++ if (tls) { ++ vs->auth = VNC_AUTH_VENCRYPT; ++ if (x509) { ++ VNC_DEBUG("Initializing VNC server with x509 password auth\n"); ++ vs->subauth = VNC_AUTH_VENCRYPT_X509VNC; ++ } else { ++ VNC_DEBUG("Initializing VNC server with TLS password auth\n"); ++ vs->subauth = VNC_AUTH_VENCRYPT_TLSVNC; ++ } ++ } else { ++#endif ++ VNC_DEBUG("Initializing VNC server with password auth\n"); ++ vs->auth = VNC_AUTH_VNC; ++#if CONFIG_VNC_TLS ++ vs->subauth = VNC_AUTH_INVALID; ++ } ++#endif ++ } else { ++#if CONFIG_VNC_TLS ++ if (tls) { ++ vs->auth = VNC_AUTH_VENCRYPT; ++ if (x509) { ++ VNC_DEBUG("Initializing VNC server with x509 no auth\n"); ++ vs->subauth = VNC_AUTH_VENCRYPT_X509NONE; ++ } else { ++ VNC_DEBUG("Initializing VNC server with TLS no auth\n"); ++ vs->subauth = VNC_AUTH_VENCRYPT_TLSNONE; ++ } ++ } else { ++#endif ++ VNC_DEBUG("Initializing VNC server with no auth\n"); ++ vs->auth = VNC_AUTH_NONE; ++#if CONFIG_VNC_TLS ++ vs->subauth = VNC_AUTH_INVALID; ++ } ++#endif + } ++#ifndef _WIN32 ++ if (strstart(display, "unix:", &p)) { ++ addr = (struct sockaddr *)&uaddr; ++ addrlen = sizeof(uaddr); ++ ++ vs->lsock = socket(PF_UNIX, SOCK_STREAM, 0); ++ if (vs->lsock == -1) { ++ fprintf(stderr, "Could not create socket\n"); ++ free(vs->display); ++ vs->display = NULL; ++ return -1; ++ } + +- ret = qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, +- NULL, vs); +- if (ret == -1) +- exit(1); ++ uaddr.sun_family = AF_UNIX; ++ memset(uaddr.sun_path, 0, 108); ++ snprintf(uaddr.sun_path, 108, "%s", p); + +- vs->ds->data = NULL; +- vs->ds->dpy_update = vnc_dpy_update; +- vs->ds->dpy_resize = vnc_dpy_resize; +- vs->ds->dpy_refresh = vnc_dpy_refresh; ++ unlink(uaddr.sun_path); ++ } else ++#endif ++ { ++ addr = (struct sockaddr *)&iaddr; ++ addrlen = sizeof(iaddr); + +- vnc_dpy_resize(vs->ds, 640, 400); ++ if (parse_host_port(&iaddr, display) < 0) { ++ fprintf(stderr, "Could not parse VNC address\n"); ++ free(vs->display); ++ vs->display = NULL; ++ return -1; ++ } ++ ++ iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900); ++ ++ vs->lsock = socket(PF_INET, SOCK_STREAM, 0); ++ if (vs->lsock == -1) { ++ fprintf(stderr, "Could not create socket\n"); ++ free(vs->display); ++ vs->display = NULL; ++ return -1; ++ } ++ ++ reuse_addr = 1; ++ ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, ++ (const char *)&reuse_addr, sizeof(reuse_addr)); ++ if (ret == -1) { ++ fprintf(stderr, "setsockopt() failed\n"); ++ close(vs->lsock); ++ vs->lsock = -1; ++ free(vs->display); ++ vs->display = NULL; ++ return -1; ++ } ++ } ++ ++ while (bind(vs->lsock, addr, addrlen) == -1) { ++ if (find_unused && errno == EADDRINUSE) { ++ iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 1); ++ continue; ++ } ++ fprintf(stderr, "bind() failed\n"); ++ close(vs->lsock); ++ vs->lsock = -1; ++ free(vs->display); ++ vs->display = NULL; ++ return -1; ++ } ++ ++ if (listen(vs->lsock, 1) == -1) { ++ fprintf(stderr, "listen() failed\n"); ++ close(vs->lsock); ++ vs->lsock = -1; ++ free(vs->display); ++ vs->display = NULL; ++ return -1; ++ } ++ ++ if (qemu_set_fd_handler2(vs->lsock, vnc_listen_poll, vnc_listen_read, NULL, vs) < 0) ++ return -1; + +- return display; ++ return ntohs(iaddr.sin_port); + } + + int vnc_start_viewer(int port) +diff -rupN xen-3.1.0-src.orig/tools/ioemu/xenstore.c xen-3.1.0-src.new/tools/ioemu/xenstore.c +--- xen-3.1.0-src.orig/tools/ioemu/xenstore.c 2007-08-28 17:02:25.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/xenstore.c 2007-08-28 17:10:41.000000000 -0400 +@@ -367,7 +367,7 @@ void xenstore_write_vncport(int display) + if (pasprintf(&buf, "%s/console/vnc-port", path) == -1) + goto out; + +- if (pasprintf(&portstr, "%d", 5900 + display) == -1) ++ if (pasprintf(&portstr, "%d", display) == -1) + goto out; + + if (xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)) == 0) +@@ -405,6 +405,7 @@ int xenstore_read_vncpasswd(int domid, c + passwd = xs_read(xsh, XBT_NULL, buf, &len); + if (passwd == NULL) { + fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf); ++ pwbuf[0] = '\0'; + free(uuid); + free(path); + return rc; +diff -rupN xen-3.1.0-src.orig/tools/python/xen/xend/image.py xen-3.1.0-src.new/tools/python/xen/xend/image.py +--- xen-3.1.0-src.orig/tools/python/xen/xend/image.py 2007-08-28 17:02:25.000000000 -0400 ++++ xen-3.1.0-src.new/tools/python/xen/xend/image.py 2007-08-28 17:22:59.000000000 -0400 +@@ -30,6 +30,7 @@ from xen.xend.XendOptions import instanc + from xen.xend.server.netif import randomMAC + from xen.xend.xenstore.xswatch import xswatch + from xen.xend import arch ++from xen.xend import XendOptions + + xc = xen.lowlevel.xc.xc() + +@@ -387,30 +388,26 @@ class HVMImageHandler(ImageHandler): + if key in vmConfig['platform']: + vnc_config[key] = vmConfig['platform'][key] + +- if not vnc_config.get('vncunused', 0) and \ +- vnc_config.get('vncdisplay', 0): +- vncdisplay = vnc_config.get('vncdisplay') +- ret.append('-vnc') +- ret.append(str(vncdisplay)) ++ if vnc_config.has_key("vncpasswd"): ++ passwd = vnc_config["vncpasswd"] + else: +- ret.append('-vncunused') ++ passwd = XendOptions.instance().get_vncpasswd_default() ++ vncopts = "" ++ if passwd: ++ self.vm.storeVm("vncpasswd", passwd) ++ vncopts = vncopts + ",password" ++ log.debug("Stored a VNC password for vfb access") ++ else: ++ log.debug("No VNC passwd configured for vfb access") + + vnclisten = vnc_config.get('vnclisten', +- xenopts().get_vnclisten_address()) +- ret.append('-vnclisten') +- ret.append(str(vnclisten)) +- +- # Store vncpassword in xenstore +- vncpasswd = vnc_config.get('vncpasswd') +- if not vncpasswd: +- vncpasswd = xenopts().get_vncpasswd_default() +- +- if vncpasswd is None: +- raise VmError('vncpasswd is not setup in vmconfig or ' +- 'xend-config.sxp') ++ XendOptions.instance().get_vnclisten_address()) ++ vncdisplay = vnc_config.get('vncdisplay', 0) ++ ret.append('-vnc') ++ ret.append("%s:%d%s" % (vnclisten, vncdisplay, vncopts)) + +- if vncpasswd != '': +- self.vm.storeVm('vncpasswd', vncpasswd) ++ if vnc_config.get('vncunused', 0): ++ ret.append('-vncunused') + elif has_sdl: + # SDL is default in QEMU. + pass +diff -rupN xen-3.1.0-src.orig/tools/python/xen/xend/server/vfbif.py xen-3.1.0-src.new/tools/python/xen/xend/server/vfbif.py +--- xen-3.1.0-src.orig/tools/python/xen/xend/server/vfbif.py 2007-08-28 17:02:25.000000000 -0400 ++++ xen-3.1.0-src.new/tools/python/xen/xend/server/vfbif.py 2007-08-28 17:09:06.000000000 -0400 +@@ -61,8 +61,10 @@ class VfbifController(DevController): + passwd = config["vncpasswd"] + else: + passwd = xen.xend.XendOptions.instance().get_vncpasswd_default() ++ vncopts = "" + if passwd: + self.vm.storeVm("vncpasswd", passwd) ++ vncopts = vncopts + ",password" + log.debug("Stored a VNC password for vfb access") + else: + log.debug("No VNC passwd configured for vfb access") +@@ -70,7 +72,7 @@ class VfbifController(DevController): + vnclisten = config.get('vnclisten', + xen.xend.XendOptions.instance().get_vnclisten_address()) + vncdisplay = config.get('vncdisplay', 0) +- args += ['-vnc', "%s:%d" % (vnclisten, vncdisplay)] ++ args += ['-vnc', "%s:%d%s" % (vnclisten, vncdisplay, vncopts)] + + if config.get('vncunused', 0): + args += ['-vncunused'] diff --git a/xen-qemu-vnc-revert-password.patch b/xen-qemu-vnc-revert-password.patch new file mode 100644 index 0000000..70c052f --- /dev/null +++ b/xen-qemu-vnc-revert-password.patch @@ -0,0 +1,747 @@ +diff -ruNp xen-3.1.0-src.orig/tools/ioemu/d3des.c xen-3.1.0-src.new/tools/ioemu/d3des.c +--- xen-3.1.0-src.orig/tools/ioemu/d3des.c 2007-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/d3des.c 1969-12-31 19:00:00.000000000 -0500 +@@ -1,434 +0,0 @@ +-/* +- * This is D3DES (V5.09) by Richard Outerbridge with the double and +- * triple-length support removed for use in VNC. Also the bytebit[] array +- * has been reversed so that the most significant bit in each byte of the +- * key is ignored, not the least significant. +- * +- * These changes are: +- * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. +- * +- * This software is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +- */ +- +-/* D3DES (V5.09) - +- * +- * A portable, public domain, version of the Data Encryption Standard. +- * +- * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. +- * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation +- * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis +- * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, +- * for humouring me on. +- * +- * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. +- * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. +- */ +- +-#include "d3des.h" +- +-static void scrunch(unsigned char *, unsigned long *); +-static void unscrun(unsigned long *, unsigned char *); +-static void desfunc(unsigned long *, unsigned long *); +-static void cookey(unsigned long *); +- +-static unsigned long KnL[32] = { 0L }; +- +-static unsigned short bytebit[8] = { +- 01, 02, 04, 010, 020, 040, 0100, 0200 }; +- +-static unsigned long bigbyte[24] = { +- 0x800000L, 0x400000L, 0x200000L, 0x100000L, +- 0x80000L, 0x40000L, 0x20000L, 0x10000L, +- 0x8000L, 0x4000L, 0x2000L, 0x1000L, +- 0x800L, 0x400L, 0x200L, 0x100L, +- 0x80L, 0x40L, 0x20L, 0x10L, +- 0x8L, 0x4L, 0x2L, 0x1L }; +- +-/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ +- +-static unsigned char pc1[56] = { +- 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, +- 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, +- 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, +- 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; +- +-static unsigned char totrot[16] = { +- 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; +- +-static unsigned char pc2[48] = { +- 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, +- 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, +- 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, +- 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 }; +- +-void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ +-unsigned char *key; +-int edf; +-{ +- register int i, j, l, m, n; +- unsigned char pc1m[56], pcr[56]; +- unsigned long kn[32]; +- +- for ( j = 0; j < 56; j++ ) { +- l = pc1[j]; +- m = l & 07; +- pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; +- } +- for( i = 0; i < 16; i++ ) { +- if( edf == DE1 ) m = (15 - i) << 1; +- else m = i << 1; +- n = m + 1; +- kn[m] = kn[n] = 0L; +- for( j = 0; j < 28; j++ ) { +- l = j + totrot[i]; +- if( l < 28 ) pcr[j] = pc1m[l]; +- else pcr[j] = pc1m[l - 28]; +- } +- for( j = 28; j < 56; j++ ) { +- l = j + totrot[i]; +- if( l < 56 ) pcr[j] = pc1m[l]; +- else pcr[j] = pc1m[l - 28]; +- } +- for( j = 0; j < 24; j++ ) { +- if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; +- if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; +- } +- } +- cookey(kn); +- return; +- } +- +-static void cookey(raw1) +-register unsigned long *raw1; +-{ +- register unsigned long *cook, *raw0; +- unsigned long dough[32]; +- register int i; +- +- cook = dough; +- for( i = 0; i < 16; i++, raw1++ ) { +- raw0 = raw1++; +- *cook = (*raw0 & 0x00fc0000L) << 6; +- *cook |= (*raw0 & 0x00000fc0L) << 10; +- *cook |= (*raw1 & 0x00fc0000L) >> 10; +- *cook++ |= (*raw1 & 0x00000fc0L) >> 6; +- *cook = (*raw0 & 0x0003f000L) << 12; +- *cook |= (*raw0 & 0x0000003fL) << 16; +- *cook |= (*raw1 & 0x0003f000L) >> 4; +- *cook++ |= (*raw1 & 0x0000003fL); +- } +- usekey(dough); +- return; +- } +- +-void cpkey(into) +-register unsigned long *into; +-{ +- register unsigned long *from, *endp; +- +- from = KnL, endp = &KnL[32]; +- while( from < endp ) *into++ = *from++; +- return; +- } +- +-void usekey(from) +-register unsigned long *from; +-{ +- register unsigned long *to, *endp; +- +- to = KnL, endp = &KnL[32]; +- while( to < endp ) *to++ = *from++; +- return; +- } +- +-void des(inblock, outblock) +-unsigned char *inblock, *outblock; +-{ +- unsigned long work[2]; +- +- scrunch(inblock, work); +- desfunc(work, KnL); +- unscrun(work, outblock); +- return; +- } +- +-static void scrunch(outof, into) +-register unsigned char *outof; +-register unsigned long *into; +-{ +- *into = (*outof++ & 0xffL) << 24; +- *into |= (*outof++ & 0xffL) << 16; +- *into |= (*outof++ & 0xffL) << 8; +- *into++ |= (*outof++ & 0xffL); +- *into = (*outof++ & 0xffL) << 24; +- *into |= (*outof++ & 0xffL) << 16; +- *into |= (*outof++ & 0xffL) << 8; +- *into |= (*outof & 0xffL); +- return; +- } +- +-static void unscrun(outof, into) +-register unsigned long *outof; +-register unsigned char *into; +-{ +- *into++ = (unsigned char)((*outof >> 24) & 0xffL); +- *into++ = (unsigned char)((*outof >> 16) & 0xffL); +- *into++ = (unsigned char)((*outof >> 8) & 0xffL); +- *into++ = (unsigned char)(*outof++ & 0xffL); +- *into++ = (unsigned char)((*outof >> 24) & 0xffL); +- *into++ = (unsigned char)((*outof >> 16) & 0xffL); +- *into++ = (unsigned char)((*outof >> 8) & 0xffL); +- *into = (unsigned char)(*outof & 0xffL); +- return; +- } +- +-static unsigned long SP1[64] = { +- 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, +- 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, +- 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, +- 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, +- 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, +- 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, +- 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, +- 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, +- 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, +- 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, +- 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, +- 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, +- 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, +- 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, +- 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, +- 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; +- +-static unsigned long SP2[64] = { +- 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, +- 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, +- 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, +- 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, +- 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, +- 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, +- 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, +- 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, +- 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, +- 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, +- 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, +- 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, +- 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, +- 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, +- 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, +- 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; +- +-static unsigned long SP3[64] = { +- 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, +- 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, +- 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, +- 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, +- 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, +- 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, +- 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, +- 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, +- 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, +- 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, +- 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, +- 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, +- 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, +- 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, +- 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, +- 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; +- +-static unsigned long SP4[64] = { +- 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, +- 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, +- 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, +- 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, +- 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, +- 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, +- 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, +- 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, +- 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, +- 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, +- 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, +- 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, +- 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, +- 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, +- 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, +- 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; +- +-static unsigned long SP5[64] = { +- 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, +- 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, +- 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, +- 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, +- 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, +- 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, +- 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, +- 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, +- 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, +- 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, +- 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, +- 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, +- 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, +- 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, +- 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, +- 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; +- +-static unsigned long SP6[64] = { +- 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, +- 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, +- 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, +- 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, +- 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, +- 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, +- 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, +- 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, +- 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, +- 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, +- 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, +- 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, +- 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, +- 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, +- 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, +- 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; +- +-static unsigned long SP7[64] = { +- 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, +- 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, +- 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, +- 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, +- 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, +- 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, +- 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, +- 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, +- 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, +- 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, +- 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, +- 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, +- 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, +- 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, +- 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, +- 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; +- +-static unsigned long SP8[64] = { +- 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, +- 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, +- 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, +- 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, +- 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, +- 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, +- 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, +- 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, +- 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, +- 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, +- 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, +- 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, +- 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, +- 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, +- 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, +- 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; +- +-static void desfunc(block, keys) +-register unsigned long *block, *keys; +-{ +- register unsigned long fval, work, right, leftt; +- register int round; +- +- leftt = block[0]; +- right = block[1]; +- work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; +- right ^= work; +- leftt ^= (work << 4); +- work = ((leftt >> 16) ^ right) & 0x0000ffffL; +- right ^= work; +- leftt ^= (work << 16); +- work = ((right >> 2) ^ leftt) & 0x33333333L; +- leftt ^= work; +- right ^= (work << 2); +- work = ((right >> 8) ^ leftt) & 0x00ff00ffL; +- leftt ^= work; +- right ^= (work << 8); +- right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; +- work = (leftt ^ right) & 0xaaaaaaaaL; +- leftt ^= work; +- right ^= work; +- leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; +- +- for( round = 0; round < 8; round++ ) { +- work = (right << 28) | (right >> 4); +- work ^= *keys++; +- fval = SP7[ work & 0x3fL]; +- fval |= SP5[(work >> 8) & 0x3fL]; +- fval |= SP3[(work >> 16) & 0x3fL]; +- fval |= SP1[(work >> 24) & 0x3fL]; +- work = right ^ *keys++; +- fval |= SP8[ work & 0x3fL]; +- fval |= SP6[(work >> 8) & 0x3fL]; +- fval |= SP4[(work >> 16) & 0x3fL]; +- fval |= SP2[(work >> 24) & 0x3fL]; +- leftt ^= fval; +- work = (leftt << 28) | (leftt >> 4); +- work ^= *keys++; +- fval = SP7[ work & 0x3fL]; +- fval |= SP5[(work >> 8) & 0x3fL]; +- fval |= SP3[(work >> 16) & 0x3fL]; +- fval |= SP1[(work >> 24) & 0x3fL]; +- work = leftt ^ *keys++; +- fval |= SP8[ work & 0x3fL]; +- fval |= SP6[(work >> 8) & 0x3fL]; +- fval |= SP4[(work >> 16) & 0x3fL]; +- fval |= SP2[(work >> 24) & 0x3fL]; +- right ^= fval; +- } +- +- right = (right << 31) | (right >> 1); +- work = (leftt ^ right) & 0xaaaaaaaaL; +- leftt ^= work; +- right ^= work; +- leftt = (leftt << 31) | (leftt >> 1); +- work = ((leftt >> 8) ^ right) & 0x00ff00ffL; +- right ^= work; +- leftt ^= (work << 8); +- work = ((leftt >> 2) ^ right) & 0x33333333L; +- right ^= work; +- leftt ^= (work << 2); +- work = ((right >> 16) ^ leftt) & 0x0000ffffL; +- leftt ^= work; +- right ^= (work << 16); +- work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; +- leftt ^= work; +- right ^= (work << 4); +- *block++ = right; +- *block = leftt; +- return; +- } +- +-/* Validation sets: +- * +- * Single-length key, single-length plaintext - +- * Key : 0123 4567 89ab cdef +- * Plain : 0123 4567 89ab cde7 +- * Cipher : c957 4425 6a5e d31d +- * +- * Double-length key, single-length plaintext - +- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 +- * Plain : 0123 4567 89ab cde7 +- * Cipher : 7f1d 0a77 826b 8aff +- * +- * Double-length key, double-length plaintext - +- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 +- * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff +- * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 +- * +- * Triple-length key, single-length plaintext - +- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 +- * Plain : 0123 4567 89ab cde7 +- * Cipher : de0b 7c06 ae5e 0ed5 +- * +- * Triple-length key, double-length plaintext - +- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 +- * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff +- * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 +- * +- * d3des V5.0a rwo 9208.07 18:44 Graven Imagery +- **********************************************************************/ +diff -ruNp xen-3.1.0-src.orig/tools/ioemu/d3des.h xen-3.1.0-src.new/tools/ioemu/d3des.h +--- xen-3.1.0-src.orig/tools/ioemu/d3des.h 2007-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/d3des.h 1969-12-31 19:00:00.000000000 -0500 +@@ -1,51 +0,0 @@ +-/* +- * This is D3DES (V5.09) by Richard Outerbridge with the double and +- * triple-length support removed for use in VNC. +- * +- * These changes are: +- * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. +- * +- * This software is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +- */ +- +-/* d3des.h - +- * +- * Headers and defines for d3des.c +- * Graven Imagery, 1992. +- * +- * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge +- * (GEnie : OUTER; CIS : [71755,204]) +- */ +- +-#define EN0 0 /* MODE == encrypt */ +-#define DE1 1 /* MODE == decrypt */ +- +-extern void deskey(unsigned char *, int); +-/* hexkey[8] MODE +- * Sets the internal key register according to the hexadecimal +- * key contained in the 8 bytes of hexkey, according to the DES, +- * for encryption or decryption according to MODE. +- */ +- +-extern void usekey(unsigned long *); +-/* cookedkey[32] +- * Loads the internal key register with the data in cookedkey. +- */ +- +-extern void cpkey(unsigned long *); +-/* cookedkey[32] +- * Copies the contents of the internal key register into the storage +- * located at &cookedkey[0]. +- */ +- +-extern void des(unsigned char *, unsigned char *); +-/* from[8] to[8] +- * Encrypts/Decrypts (according to the key currently loaded in the +- * internal key register) one block of eight bytes at address 'from' +- * into the block at address 'to'. They can be the same. +- */ +- +-/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery +- ********************************************************************/ +diff -ruNp 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 15:33:41.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/Makefile.target 2007-08-23 15:35:32.000000000 -0400 +@@ -412,7 +412,6 @@ ifdef CONFIG_SDL + VL_OBJS+=sdl.o + endif + VL_OBJS+=vnc.o +-VL_OBJS+=d3des.o + ifdef CONFIG_COCOA + VL_OBJS+=cocoa.o + COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit +@@ -473,9 +472,6 @@ sdl.o: sdl.c keymaps.c sdl_keysym.h + vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< + +-d3des.o: d3des.c d3des.h +- $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< +- + sdlaudio.o: sdlaudio.c + $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< + +diff -ruNp xen-3.1.0-src.orig/tools/ioemu/vl.c xen-3.1.0-src.new/tools/ioemu/vl.c +--- xen-3.1.0-src.orig/tools/ioemu/vl.c 2007-08-23 15:33:41.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.c 2007-08-23 15:35:32.000000000 -0400 +@@ -171,9 +171,6 @@ time_t timeoffset = 0; + char domain_name[1024] = "Xen-no-name"; + extern int domid; + +-char vncpasswd[64]; +-unsigned char challenge[AUTHCHALLENGESIZE]; +- + /***********************************************************/ + /* x86 ISA bus support */ + +@@ -6004,7 +6001,6 @@ int main(int argc, char **argv) + vncunused = 0; + kernel_filename = NULL; + kernel_cmdline = ""; +- *vncpasswd = '\0'; + #ifndef CONFIG_DM + #ifdef TARGET_PPC + cdrom_index = 1; +@@ -6553,10 +6549,6 @@ int main(int argc, char **argv) + + init_ioports(); + +- /* read vncpasswd from xenstore */ +- if (0 > xenstore_read_vncpasswd(domid)) +- exit(1); +- + /* terminal init */ + if (nographic) { + dumb_display_init(ds); +diff -ruNp xen-3.1.0-src.orig/tools/ioemu/vl.h xen-3.1.0-src.new/tools/ioemu/vl.h +--- xen-3.1.0-src.orig/tools/ioemu/vl.h 2007-08-23 15:33:41.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vl.h 2007-08-23 15:40:33.000000000 -0400 +@@ -1246,7 +1246,7 @@ int xenstore_fd(void); + void xenstore_process_event(void *opaque); + void xenstore_check_new_media_present(int timeout); + void xenstore_write_vncport(int vnc_display); +-int xenstore_read_vncpasswd(int domid); ++int xenstore_read_vncpasswd(int domid, char *pwbuf, size_t pwbuflen); + + int xenstore_domain_has_devtype(struct xs_handle *handle, + const char *devtype); +@@ -1283,7 +1283,4 @@ extern char domain_name[]; + + void destroy_hvm_domain(void); + +-/* VNC Authentication */ +-#define AUTHCHALLENGESIZE 16 +- + #endif /* VL_H */ +diff -ruNp xen-3.1.0-src.orig/tools/ioemu/vnc.c xen-3.1.0-src.new/tools/ioemu/vnc.c +--- xen-3.1.0-src.orig/tools/ioemu/vnc.c 2007-05-18 10:45:21.000000000 -0400 ++++ xen-3.1.0-src.new/tools/ioemu/vnc.c 2007-08-23 15:42:10.000000000 -0400 +@@ -44,7 +44,6 @@ + + #include "vnc_keysym.h" + #include "keymaps.c" +-#include "d3des.h" + + #define XK_MISCELLANY + #define XK_LATIN1 +@@ -140,9 +139,6 @@ static void _vnc_update_client(void *opa + static void vnc_update_client(void *opaque); + static void vnc_client_read(void *opaque); + static void framebuffer_set_updated(VncState *vs, int x, int y, int w, int h); +-static int make_challenge(unsigned char *random, int size); +-static void set_seed(unsigned int *seedp); +-static void get_random(int len, unsigned char *buf); + + #if 0 + static inline void vnc_set_bit(uint32_t *d, int k) +@@ -1260,92 +1256,24 @@ static int protocol_client_init(VncState + return 0; + } + +-static int protocol_response(VncState *vs, uint8_t *client_response, size_t len) +-{ +- extern char vncpasswd[64]; +- extern unsigned char challenge[AUTHCHALLENGESIZE]; +- unsigned char cryptchallenge[AUTHCHALLENGESIZE]; +- unsigned char key[8]; +- int passwdlen, i, j; +- +- memcpy(cryptchallenge, challenge, AUTHCHALLENGESIZE); +- +- /* Calculate the sent challenge */ +- passwdlen = strlen(vncpasswd); +- for (i=0; i<8; i++) +- key[i] = ivtpm_instance)) { ++ if (1 == vTPMTransmit[idx].open_fn(s, s->vtpm_instance)) { + /* found one */ + s->Transmitlayer = idx; + break; +@@ -213,7 +213,7 @@ static void open_vtpm_channel(tpmState * + */ + static inline void close_vtpm_channel(tpmState *s, int force) + { +- if (1 == vTPMTransmit[s->Transmitlayer].close(s, force)) { ++ if (1 == vTPMTransmit[s->Transmitlayer].close_fn(s, force)) { + s->Transmitlayer = -1; + } + } +@@ -974,7 +974,7 @@ static int TPM_Send(tpmState *s, tpmBuff + buffer->instance[0] &= 0x1f; + buffer->instance[0] |= (locty << 5); + +- len = vTPMTransmit[s->Transmitlayer].write(s, buffer); ++ len = vTPMTransmit[s->Transmitlayer].write_fn(s, buffer); + if (len < 0) { + s->Transmitlayer = -1; + } +@@ -990,7 +990,7 @@ static int TPM_Receive(tpmState *s, tpmB + { + int off; + +- off = vTPMTransmit[s->Transmitlayer].read(s, buffer); ++ off = vTPMTransmit[s->Transmitlayer].read_fn(s, buffer); + + if (off < 0) { + /* EAGAIN is set in errno due to non-blocking mode */ diff --git a/xen.spec b/xen.spec index 78a8e08..e7f5781 100644 --- a/xen.spec +++ b/xen.spec @@ -3,12 +3,11 @@ Summary: Xen is a virtual machine monitor Name: xen Version: 3.1.0 -Release: 3%{?dist} +Release: 4%{?dist} Group: Development/Libraries License: GPL URL: http://www.cl.cam.ac.uk/Research/SRG/netos/xen/index.html Source0: %{name}-%{version}-src.tgz -Source1: http://download.sf.net/libvncserver/LibVNCServer-0.8.2.tar.gz Source2: %{name}.modules Source3: %{name}.sysconfig Source4: %{name}.logrotate @@ -27,6 +26,7 @@ Patch27: xen-console-log.patch Patch28: xen-keyboard.patch Patch29: xen-3.1.0-libxc-native-protocol.patch Patch30: xen-3.1.0-dev-native-protocol.patch +Patch31: xen-tpm-functions.patch # Patches to modify the default config of xend Patch100: xen-config-dom0-minmem.patch @@ -39,18 +39,20 @@ Patch150: xen-pvfb-compat.patch Patch151: xen-pvfb-terminate.patch Patch152: xen-pvfb-no-hvm.patch +Patch160: xen-pvfb-01-qemu-fv-machine.patch +Patch161: xen-pvfb-02-qemu-pv-machine.patch +Patch162: xen-pvfb-03-xenfb-remove.patch + +Patch163: xen-qemu-vnc-revert-password.patch + +Patch164: xen-qemu-iohandler-delete.patch +Patch165: xen-qemu-vnc-authentication.patch + Patch251: pygrub-manykernels.patch # Performance fix for listing domains Patch280: xen-xs-transactions.patch -# libVNCserver patches -Patch300: vnc-thread-fixes.patch -Patch301: vnc-invalid-fd.patch -Patch302: vnc-ref-counting.patch -Patch303: vnc-client-iterator.patch -Patch304: vnc-double-cleanup.patch - BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root BuildRequires: transfig libidn-devel zlib-devel texi2html SDL-devel curl-devel BuildRequires: libX11-devel python-devel ghostscript tetex-latex @@ -66,6 +68,7 @@ BuildRequires: /usr/include/gnu/stubs-32.h BuildRequires: dev86 %endif BuildRequires: gettext +BuildRequires: gnutls-devel Requires: bridge-utils Requires: udev >= 059 Requires: python-virtinst @@ -107,7 +110,7 @@ This package contains what's needed to develop applications to manage Xen virtual machines. %prep -%setup -q -n %{name}-%{version}-src -a 1 +%setup -q -n %{name}-%{version}-src %patch1 -p1 -b .init %patch3 -p1 -b .compile %patch6 -p1 @@ -124,15 +127,30 @@ virtual machines. %patch29 -p1 %patch30 -p1 +%patch31 -p1 + # config patches %patch100 -p1 %patch102 -p1 %patch103 -p1 # pvfb compat -%patch150 -p1 -%patch151 -p1 -%patch152 -p1 +# XXX re-instate this somehow ??!?! +#patch150 -p1 +#patch151 -p1 +#patch152 -p1 + +# Switch to QEMU for paravirt VNC server +%patch160 -p1 +%patch161 -p1 +%patch162 -p1 + +# Remove old VNC password code +%patch163 -p1 + +# Add new TLS code +%patch164 -p1 +%patch165 -p1 # upstream patches %patch251 -p1 @@ -140,34 +158,7 @@ virtual machines. # performance patch %patch280 -p1 -# libVNCserver patches -pushd LibVNCServer-0.8.2 -# thread locking fixes -%patch300 -p2 -# use of invalid fd (race condition) -%patch301 -p2 -# dangling pointer (race condition) -%patch302 -p2 -# client iterator fixes -%patch303 -p2 -# double cleanup (race condition) -%patch304 -p2 -popd - %build -# libvncserver first -pushd LibVNCServer-0.8.2 -%configure -make -C libvncserver -vncdir=`pwd` -popd -sed -i -e "s;libvncserver-config;${vncdir}/libvncserver-config;" tools/xenfb/Makefile -cat > tools/check/check_libvncserver < - 3.1.0-4.fc8 +- Switch PVFB over to use QEMU +- Backport QEMU VNC security patches for TLS/x509 + * Wed Aug 1 2007 Markus Armbruster - 3.1.0-3.fc8 - Put guest's native protocol ABI into xenstore, to provide for older kernels running 32-on-64.