diff --git a/po/POTFILES.in b/po/POTFILES.in
index 2256cb2..7fbbe8f 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -119,6 +119,7 @@ src/xen/xm_internal.c
 src/xen/xs_internal.c
 src/xenapi/xenapi_driver.c
 src/xenapi/xenapi_utils.c
+src/xenxs/xen_sxpr.c
 tools/console.c
 tools/libvirt-guests.init.sh
 tools/virsh.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 5c9b019..1e670e5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -423,6 +423,10 @@ CPU_SOURCES =							\
 VMX_SOURCES =							\
 		vmx/vmx.c vmx/vmx.h
 
+XENXS_SOURCES =							\
+		xenxs/xenxs_private.h				\
+		xenxs/xen_sxpr.c xenxs/xen_sxpr.h
+
 pkgdata_DATA =	cpu/cpu_map.xml
 
 EXTRA_DIST +=	$(pkgdata_DATA)
@@ -464,6 +468,14 @@ libvirt_vmx_la_CFLAGS = \
 libvirt_vmx_la_SOURCES = $(VMX_SOURCES)
 endif
 
+if WITH_XEN
+noinst_LTLIBRARIES += libvirt_xenxs.la
+libvirt_la_BUILT_LIBADD += libvirt_xenxs.la
+libvirt_xenxs_la_CFLAGS = \
+		-I@top_srcdir@/src/conf $(AM_CFLAGS)
+libvirt_xenxs_la_SOURCES = $(XENXS_SOURCES)
+endif
+
 
 noinst_LTLIBRARIES += libvirt_driver.la
 libvirt_la_BUILT_LIBADD += libvirt_driver.la
@@ -583,6 +595,7 @@ endif
 libvirt_driver_xen_la_CFLAGS =					\
 		$(XEN_CFLAGS)					\
 		-I@top_srcdir@/src/conf				\
+		-I@top_srcdir@/src/xenxs			\
 		$(AM_CFLAGS)
 libvirt_driver_xen_la_LDFLAGS = $(AM_LDFLAGS)
 libvirt_driver_xen_la_LIBADD = $(XEN_LIBS)
diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c
index b14c8db..6e3028a 100644
--- a/src/xen/xen_driver.c
+++ b/src/xen/xen_driver.c
@@ -33,6 +33,7 @@
 #include "datatypes.h"
 #include "xen_driver.h"
 
+#include "xen_sxpr.h"
 #include "xen_hypervisor.h"
 #include "xend_internal.h"
 #include "xs_internal.h"
@@ -1198,6 +1199,9 @@ xenUnifiedDomainXMLFromNative(virConnectPtr conn,
     virDomainDefPtr def = NULL;
     char *ret = NULL;
     virConfPtr conf = NULL;
+    int id;
+    char * tty;
+    int vncport;
     GET_PRIVATE(conn);
 
     if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
@@ -1214,7 +1218,13 @@ xenUnifiedDomainXMLFromNative(virConnectPtr conn,
 
         def = xenXMDomainConfigParse(conn, conf);
     } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
-        def = xenDaemonParseSxprString(conn, config, priv->xendConfigVersion);
+        id = xenGetDomIdFromSxprString(config, priv->xendConfigVersion);
+        xenUnifiedLock(priv);
+        tty = xenStoreDomainGetConsolePath(conn, id);
+        vncport = xenStoreDomainGetVNCPort(conn, id);
+        xenUnifiedUnlock(priv);
+        def = xenDaemonParseSxprString(config, priv->xendConfigVersion, tty,
+                                       vncport);
     }
     if (!def)
         goto cleanup;
diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c
index 6f98dc0..70f6ac4 100644
--- a/src/xen/xend_internal.c
+++ b/src/xen/xend_internal.c
@@ -38,6 +38,7 @@
 #include "driver.h"
 #include "util.h"
 #include "sexpr.h"
+#include "xen_sxpr.h"
 #include "buf.h"
 #include "uuid.h"
 #include "xen_driver.h"
@@ -1040,1307 +1041,6 @@ xend_detect_config_version(virConnectPtr conn) {
 }
 
 
-/*****************************************************************
- ******
- ****** Parsing of SEXPR into virDomainDef objects
- ******
- *****************************************************************/
-
-/**
- * xenDaemonParseSxprOS
- * @node: the root of the parsed S-Expression
- * @def: the domain config
- * @hvm: true or 1 if no contains HVM S-Expression
- * @bootloader: true or 1 if a bootloader is defined
- *
- * Parse the xend sexp for description of os and append it to buf.
- *
- * Returns 0 in case of success and -1 in case of error
- */
-static int
-xenDaemonParseSxprOS(const struct sexpr *node,
-                     virDomainDefPtr def,
-                     int hvm)
-{
-    if (hvm) {
-        if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0)
-            goto no_memory;
-        if (def->os.loader == NULL) {
-            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0)
-                goto no_memory;
-
-            if (def->os.loader == NULL) {
-                virXendError(VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("domain information incomplete, missing HVM loader"));
-                return(-1);
-            }
-        } else {
-            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0)
-                goto no_memory;
-            if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0)
-                goto no_memory;
-            if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0)
-                goto no_memory;
-            if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0)
-                goto no_memory;
-        }
-    } else {
-        if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0)
-            goto no_memory;
-        if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0)
-            goto no_memory;
-        if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0)
-            goto no_memory;
-        if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0)
-            goto no_memory;
-    }
-
-    /* If HVM kenrel == loader, then old xend, so kill off kernel */
-    if (hvm &&
-        def->os.kernel &&
-        STREQ(def->os.kernel, def->os.loader)) {
-        VIR_FREE(def->os.kernel);
-    }
-
-    if (!def->os.kernel &&
-        hvm) {
-        const char *boot = sexpr_node(node, "domain/image/hvm/boot");
-        if ((boot != NULL) && (boot[0] != 0)) {
-            while (*boot &&
-                   def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) {
-                if (*boot == 'a')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY;
-                else if (*boot == 'c')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK;
-                else if (*boot == 'd')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM;
-                else if (*boot == 'n')
-                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET;
-                boot++;
-            }
-        }
-    }
-
-    if (!hvm &&
-        !def->os.kernel &&
-        !def->os.bootloader) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing kernel & bootloader"));
-        return -1;
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError();
-    return -1;
-}
-
-virDomainChrDefPtr
-xenDaemonParseSxprChar(const char *value,
-                       const char *tty)
-{
-    const char *prefix;
-    char *tmp;
-    virDomainChrDefPtr def;
-
-    if (VIR_ALLOC(def) < 0) {
-        virReportOOMError();
-        return NULL;
-    }
-
-    prefix = value;
-
-    if (value[0] == '/') {
-        def->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
-    } else {
-        if ((tmp = strchr(value, ':')) != NULL) {
-            *tmp = '\0';
-            value = tmp + 1;
-        }
-
-        if (STRPREFIX(prefix, "telnet")) {
-            def->source.type = VIR_DOMAIN_CHR_TYPE_TCP;
-            def->source.data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
-        } else {
-            if ((def->source.type = virDomainChrTypeFromString(prefix)) < 0) {
-                virXendError(VIR_ERR_INTERNAL_ERROR,
-                             _("unknown chr device type '%s'"), prefix);
-                goto error;
-            }
-        }
-    }
-
-    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
-    switch (def->source.type) {
-    case VIR_DOMAIN_CHR_TYPE_PTY:
-        if (tty != NULL &&
-            !(def->source.data.file.path = strdup(tty)))
-            goto no_memory;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_FILE:
-    case VIR_DOMAIN_CHR_TYPE_PIPE:
-        if (!(def->source.data.file.path = strdup(value)))
-            goto no_memory;
-        break;
-
-    case VIR_DOMAIN_CHR_TYPE_TCP:
-    {
-        const char *offset = strchr(value, ':');
-        const char *offset2;
-
-        if (offset == NULL) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            (def->source.data.tcp.host = strndup(value,
-                                                 offset - value)) == NULL)
-            goto no_memory;
-
-        offset2 = strchr(offset, ',');
-        if (offset2 == NULL)
-            def->source.data.tcp.service = strdup(offset+1);
-        else
-            def->source.data.tcp.service = strndup(offset+1,
-                                                   offset2-(offset+1));
-        if (def->source.data.tcp.service == NULL)
-            goto no_memory;
-
-        if (offset2 && strstr(offset2, ",server"))
-            def->source.data.tcp.listen = true;
-    }
-    break;
-
-    case VIR_DOMAIN_CHR_TYPE_UDP:
-    {
-        const char *offset = strchr(value, ':');
-        const char *offset2, *offset3;
-
-        if (offset == NULL) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("malformed char device string"));
-            goto error;
-        }
-
-        if (offset != value &&
-            (def->source.data.udp.connectHost
-             = strndup(value, offset - value)) == NULL)
-            goto no_memory;
-
-        offset2 = strchr(offset, '@');
-        if (offset2 != NULL) {
-            if ((def->source.data.udp.connectService
-                 = strndup(offset + 1, offset2-(offset+1))) == NULL)
-                goto no_memory;
-
-            offset3 = strchr(offset2, ':');
-            if (offset3 == NULL) {
-                virXendError(VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("malformed char device string"));
-                goto error;
-            }
-
-            if (offset3 > (offset2 + 1) &&
-                (def->source.data.udp.bindHost
-                 = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
-                goto no_memory;
-
-            if ((def->source.data.udp.bindService
-                 = strdup(offset3 + 1)) == NULL)
-                goto no_memory;
-        } else {
-            if ((def->source.data.udp.connectService
-                 = strdup(offset + 1)) == NULL)
-                goto no_memory;
-        }
-    }
-    break;
-
-    case VIR_DOMAIN_CHR_TYPE_UNIX:
-    {
-        const char *offset = strchr(value, ',');
-        if (offset)
-            def->source.data.nix.path = strndup(value, (offset - value));
-        else
-            def->source.data.nix.path = strdup(value);
-        if (def->source.data.nix.path == NULL)
-            goto no_memory;
-
-        if (offset != NULL &&
-            strstr(offset, ",server") != NULL)
-            def->source.data.nix.listen = true;
-    }
-    break;
-    }
-
-    return def;
-
-no_memory:
-    virReportOOMError();
-error:
-    virDomainChrDefFree(def);
-    return NULL;
-}
-
-/**
- * xend_parse_sexp_desc_disks
- * @conn: connection
- * @root: root sexpr
- * @xendConfigVersion: version of xend
- *
- * This parses out block devices from the domain sexpr
- *
- * Returns 0 if successful or -1 if failed.
- */
-static int
-xenDaemonParseSxprDisks(virDomainDefPtr def,
-                        const struct sexpr *root,
-                        int hvm,
-                        int xendConfigVersion)
-{
-    const struct sexpr *cur, *node;
-    virDomainDiskDefPtr disk = NULL;
-
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        /* Normally disks are in a (device (vbd ...)) block
-           but blktap disks ended up in a differently named
-           (device (tap ....)) block.... */
-        if (sexpr_lookup(node, "device/vbd") ||
-            sexpr_lookup(node, "device/tap") ||
-            sexpr_lookup(node, "device/tap2")) {
-            char *offset;
-            const char *src = NULL;
-            const char *dst = NULL;
-            const char *mode = NULL;
-
-            /* Again dealing with (vbd...) vs (tap ...) differences */
-            if (sexpr_lookup(node, "device/vbd")) {
-                src = sexpr_node(node, "device/vbd/uname");
-                dst = sexpr_node(node, "device/vbd/dev");
-                mode = sexpr_node(node, "device/vbd/mode");
-            } else if (sexpr_lookup(node, "device/tap2")) {
-                src = sexpr_node(node, "device/tap2/uname");
-                dst = sexpr_node(node, "device/tap2/dev");
-                mode = sexpr_node(node, "device/tap2/mode");
-            } else {
-                src = sexpr_node(node, "device/tap/uname");
-                dst = sexpr_node(node, "device/tap/dev");
-                mode = sexpr_node(node, "device/tap/mode");
-            }
-
-            if (VIR_ALLOC(disk) < 0)
-                goto no_memory;
-
-            if (dst == NULL) {
-                virXendError(VIR_ERR_INTERNAL_ERROR,
-                             "%s", _("domain information incomplete, vbd has no dev"));
-                goto error;
-            }
-
-            if (src == NULL) {
-                /* There is a case without the uname to the CD-ROM device */
-                offset = strchr(dst, ':');
-                if (!offset ||
-                    !hvm ||
-                    STRNEQ(offset, ":cdrom")) {
-                    virXendError(VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("domain information incomplete, vbd has no src"));
-                    goto error;
-                }
-            }
-
-            if (src != NULL) {
-                offset = strchr(src, ':');
-                if (!offset) {
-                    virXendError(VIR_ERR_INTERNAL_ERROR,
-                                 "%s", _("cannot parse vbd filename, missing driver name"));
-                    goto error;
-                }
-
-                if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
-                    goto no_memory;
-                if (virStrncpy(disk->driverName, src, offset-src,
-                              (offset-src)+1) == NULL) {
-                    virXendError(VIR_ERR_INTERNAL_ERROR,
-                                 _("Driver name %s too big for destination"),
-                                 src);
-                    goto error;
-                }
-
-                src = offset + 1;
-
-                if (STREQ (disk->driverName, "tap") ||
-                    STREQ (disk->driverName, "tap2")) {
-                    offset = strchr(src, ':');
-                    if (!offset) {
-                        virXendError(VIR_ERR_INTERNAL_ERROR,
-                                     "%s", _("cannot parse vbd filename, missing driver type"));
-                        goto error;
-                    }
-
-                    if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0)
-                        goto no_memory;
-                    if (virStrncpy(disk->driverType, src, offset-src,
-                                   (offset-src)+1) == NULL) {
-                        virXendError(VIR_ERR_INTERNAL_ERROR,
-                                     _("Driver type %s too big for destination"),
-                                     src);
-                        goto error;
-                    }
-
-                    src = offset + 1;
-                    /* Its possible to use blktap driver for block devs
-                       too, but kinda pointless because blkback is better,
-                       so we assume common case here. If blktap becomes
-                       omnipotent, we can revisit this, perhaps stat()'ing
-                       the src file in question */
-                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-                } else if (STREQ(disk->driverName, "phy")) {
-                    disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
-                } else if (STREQ(disk->driverName, "file")) {
-                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-                }
-            } else {
-                /* No CDROM media so can't really tell. We'll just
-                   call if a FILE for now and update when media
-                   is inserted later */
-                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            }
-
-            if (STREQLEN (dst, "ioemu:", 6))
-                dst += 6;
-
-            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
-            /* New style disk config from Xen >= 3.0.3 */
-            if (xendConfigVersion > 1) {
-                offset = strrchr(dst, ':');
-                if (offset) {
-                    if (STREQ (offset, ":cdrom")) {
-                        disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-                    } else if (STREQ (offset, ":disk")) {
-                        /* The default anyway */
-                    } else {
-                        /* Unknown, lets pretend its a disk too */
-                    }
-                    offset[0] = '\0';
-                }
-            }
-
-            if (!(disk->dst = strdup(dst)))
-                goto no_memory;
-            if (src &&
-                !(disk->src = strdup(src)))
-                goto no_memory;
-
-            if (STRPREFIX(disk->dst, "xvd"))
-                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
-            else if (STRPREFIX(disk->dst, "hd"))
-                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-            else if (STRPREFIX(disk->dst, "sd"))
-                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
-            else
-                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-
-            if (mode &&
-                strchr(mode, 'r'))
-                disk->readonly = 1;
-            if (mode &&
-                strchr(mode, '!'))
-                disk->shared = 1;
-
-            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
-                goto no_memory;
-
-            def->disks[def->ndisks++] = disk;
-            disk = NULL;
-        }
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError();
-
-error:
-    virDomainDiskDefFree(disk);
-    return -1;
-}
-
-
-static int
-xenDaemonParseSxprNets(virDomainDefPtr def,
-                       const struct sexpr *root)
-{
-    virDomainNetDefPtr net = NULL;
-    const struct sexpr *cur, *node;
-    const char *tmp;
-    int vif_index = 0;
-
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if (sexpr_lookup(node, "device/vif")) {
-            const char *tmp2, *model, *type;
-            char buf[50];
-            tmp2 = sexpr_node(node, "device/vif/script");
-            tmp = sexpr_node(node, "device/vif/bridge");
-            model = sexpr_node(node, "device/vif/model");
-            type = sexpr_node(node, "device/vif/type");
-
-            if (VIR_ALLOC(net) < 0)
-                goto no_memory;
-
-            if (tmp != NULL ||
-                (tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
-                net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
-                /* XXX virtual network reverse resolve */
-
-                if (tmp &&
-                    !(net->data.bridge.brname = strdup(tmp)))
-                    goto no_memory;
-                if (tmp2 &&
-                    net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
-                    !(net->data.bridge.script = strdup(tmp2)))
-                    goto no_memory;
-                tmp = sexpr_node(node, "device/vif/ip");
-                if (tmp &&
-                    !(net->data.bridge.ipaddr = strdup(tmp)))
-                    goto no_memory;
-            } else {
-                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
-                if (tmp2 &&
-                    !(net->data.ethernet.script = strdup(tmp2)))
-                    goto no_memory;
-                tmp = sexpr_node(node, "device/vif/ip");
-                if (tmp &&
-                    !(net->data.ethernet.ipaddr = strdup(tmp)))
-                    goto no_memory;
-            }
-
-            tmp = sexpr_node(node, "device/vif/vifname");
-            if (!tmp) {
-                snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index);
-                tmp = buf;
-            }
-            if (!(net->ifname = strdup(tmp)))
-                goto no_memory;
-
-            tmp = sexpr_node(node, "device/vif/mac");
-            if (tmp) {
-                if (virParseMacAddr(tmp, net->mac) < 0) {
-                    virXendError(VIR_ERR_INTERNAL_ERROR,
-                                 _("malformed mac address '%s'"), tmp);
-                    goto cleanup;
-                }
-            }
-
-            if (model &&
-                !(net->model = strdup(model)))
-                goto no_memory;
-
-            if (!model && type &&
-                STREQ(type, "netfront") &&
-                !(net->model = strdup("netfront")))
-                goto no_memory;
-
-            if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
-                goto no_memory;
-
-            def->nets[def->nnets++] = net;
-            vif_index++;
-        }
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError();
-cleanup:
-    virDomainNetDefFree(net);
-    return -1;
-}
-
-
-int
-xenDaemonParseSxprSound(virDomainDefPtr def,
-                        const char *str)
-{
-    if (STREQ(str, "all")) {
-        int i;
-
-        /*
-         * Special compatability code for Xen with a bogus
-         * sound=all in config.
-         *
-         * NB delibrately, don't include all possible
-         * sound models anymore, just the 2 that were
-         * historically present in Xen's QEMU.
-         *
-         * ie just es1370 + sb16.
-         *
-         * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
-         */
-
-        if (VIR_ALLOC_N(def->sounds,
-                        VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
-            goto no_memory;
-
-
-        for (i = 0 ; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) ; i++) {
-            virDomainSoundDefPtr sound;
-            if (VIR_ALLOC(sound) < 0)
-                goto no_memory;
-            sound->model = i;
-            def->sounds[def->nsounds++] = sound;
-        }
-    } else {
-        char model[10];
-        const char *offset = str, *offset2;
-
-        do {
-            int len;
-            virDomainSoundDefPtr sound;
-            offset2 = strchr(offset, ',');
-            if (offset2)
-                len = (offset2 - offset);
-            else
-                len = strlen(offset);
-            if (virStrncpy(model, offset, len, sizeof(model)) == NULL) {
-                virXendError(VIR_ERR_INTERNAL_ERROR,
-                                 _("Sound model %s too big for destination"),
-                             offset);
-                goto error;
-            }
-
-            if (VIR_ALLOC(sound) < 0)
-                goto no_memory;
-
-            if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
-                VIR_FREE(sound);
-                goto error;
-            }
-
-            if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
-                virDomainSoundDefFree(sound);
-                goto no_memory;
-            }
-
-            def->sounds[def->nsounds++] = sound;
-            offset = offset2 ? offset2 + 1 : NULL;
-        } while (offset);
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError();
-error:
-    return -1;
-}
-
-
-static int
-xenDaemonParseSxprUSB(virDomainDefPtr def,
-                      const struct sexpr *root)
-{
-    struct sexpr *cur, *node;
-    const char *tmp;
-
-    for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if (sexpr_lookup(node, "usbdevice")) {
-            tmp = sexpr_node(node, "usbdevice");
-            if (tmp && *tmp) {
-                if (STREQ(tmp, "tablet") ||
-                    STREQ(tmp, "mouse")) {
-                    virDomainInputDefPtr input;
-                    if (VIR_ALLOC(input) < 0)
-                        goto no_memory;
-                    input->bus = VIR_DOMAIN_INPUT_BUS_USB;
-                    if (STREQ(tmp, "tablet"))
-                        input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
-                    else
-                        input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
-
-                    if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
-                        VIR_FREE(input);
-                        goto no_memory;
-                    }
-                    def->inputs[def->ninputs++] = input;
-                } else {
-                    /* XXX Handle other non-input USB devices later */
-                }
-            }
-        }
-    }
-    return 0;
-
-no_memory:
-    virReportOOMError();
-    return -1;
-}
-
-static int
-xenDaemonParseSxprGraphicsOld(virConnectPtr conn,
-                              virDomainDefPtr def,
-                              const struct sexpr *root,
-                              int hvm,
-                              int xendConfigVersion)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    const char *tmp;
-    virDomainGraphicsDefPtr graphics = NULL;
-
-    if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
-        tmp[0] == '1') {
-        /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
-        int port;
-        const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
-        const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
-        const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
-        const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
-
-        xenUnifiedLock(priv);
-        port = xenStoreDomainGetVNCPort(conn, def->id);
-        xenUnifiedUnlock(priv);
-
-        if (VIR_ALLOC(graphics) < 0)
-            goto no_memory;
-
-        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
-        /* For Xen >= 3.0.3, don't generate a fixed port mapping
-         * because it will almost certainly be wrong ! Just leave
-         * it as -1 which lets caller see that the VNC server isn't
-         * present yet. Subsquent dumps of the XML will eventually
-         * find the port in XenStore once VNC server has started
-         */
-        if (port == -1 && xendConfigVersion < 2)
-            port = 5900 + def->id;
-
-        if ((unused && STREQ(unused, "1")) || port == -1)
-            graphics->data.vnc.autoport = 1;
-        graphics->data.vnc.port = port;
-
-        if (listenAddr &&
-            !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
-            goto no_memory;
-
-        if (vncPasswd &&
-            !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
-            goto no_memory;
-
-        if (keymap &&
-            !(graphics->data.vnc.keymap = strdup(keymap)))
-            goto no_memory;
-
-        if (VIR_ALLOC_N(def->graphics, 1) < 0)
-            goto no_memory;
-        def->graphics[0] = graphics;
-        def->ngraphics = 1;
-        graphics = NULL;
-    } else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) &&
-               tmp[0] == '1') {
-        /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */
-        const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux");
-        const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux");
-
-        if (VIR_ALLOC(graphics) < 0)
-            goto no_memory;
-
-        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
-        if (display &&
-            !(graphics->data.sdl.display = strdup(display)))
-            goto no_memory;
-        if (xauth &&
-            !(graphics->data.sdl.xauth = strdup(xauth)))
-            goto no_memory;
-
-        if (VIR_ALLOC_N(def->graphics, 1) < 0)
-            goto no_memory;
-        def->graphics[0] = graphics;
-        def->ngraphics = 1;
-        graphics = NULL;
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError();
-    virDomainGraphicsDefFree(graphics);
-    return -1;
-}
-
-
-static int
-xenDaemonParseSxprGraphicsNew(virConnectPtr conn,
-                              virDomainDefPtr def,
-                              const struct sexpr *root)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    virDomainGraphicsDefPtr graphics = NULL;
-    const struct sexpr *cur, *node;
-    const char *tmp;
-
-    /* append network devices and framebuffer */
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if (sexpr_lookup(node, "device/vfb")) {
-            /* New style graphics config for PV guests in >= 3.0.4,
-             * or for HVM guests in >= 3.0.5 */
-            if (sexpr_node(node, "device/vfb/type")) {
-                tmp = sexpr_node(node, "device/vfb/type");
-            } else if (sexpr_node(node, "device/vfb/vnc")) {
-                tmp = "vnc";
-            } else if (sexpr_node(node, "device/vfb/sdl")) {
-                tmp = "sdl";
-            } else {
-                tmp = "unknown";
-            }
-
-            if (VIR_ALLOC(graphics) < 0)
-                goto no_memory;
-
-            if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
-                virXendError(VIR_ERR_INTERNAL_ERROR,
-                             _("unknown graphics type '%s'"), tmp);
-                goto error;
-            }
-
-            if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
-                const char *display = sexpr_node(node, "device/vfb/display");
-                const char *xauth = sexpr_node(node, "device/vfb/xauthority");
-                if (display &&
-                    !(graphics->data.sdl.display = strdup(display)))
-                    goto no_memory;
-                if (xauth &&
-                    !(graphics->data.sdl.xauth = strdup(xauth)))
-                    goto no_memory;
-            } else {
-                int port;
-                const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
-                const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");
-                const char *keymap = sexpr_node(node, "device/vfb/keymap");
-                const char *unused = sexpr_node(node, "device/vfb/vncunused");
-
-                xenUnifiedLock(priv);
-                port = xenStoreDomainGetVNCPort(conn, def->id);
-                xenUnifiedUnlock(priv);
-
-                /* Didn't find port entry in xenstore */
-                if (port == -1) {
-                    const char *str = sexpr_node(node, "device/vfb/vncdisplay");
-                    int val;
-                    if (str != NULL && virStrToLong_i(str, NULL, 0, &val) == 0)
-                        port = val;
-                }
-
-                if ((unused && STREQ(unused, "1")) || port == -1)
-                    graphics->data.vnc.autoport = 1;
-
-                if (port >= 0 && port < 5900)
-                    port += 5900;
-                graphics->data.vnc.port = port;
-
-                if (listenAddr &&
-                    !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
-                    goto no_memory;
-
-                if (vncPasswd &&
-                    !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
-                    goto no_memory;
-
-                if (keymap &&
-                    !(graphics->data.vnc.keymap = strdup(keymap)))
-                    goto no_memory;
-            }
-
-            if (VIR_ALLOC_N(def->graphics, 1) < 0)
-                goto no_memory;
-            def->graphics[0] = graphics;
-            def->ngraphics = 1;
-            graphics = NULL;
-            break;
-        }
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError();
-error:
-    virDomainGraphicsDefFree(graphics);
-    return -1;
-}
-
-/**
- * xenDaemonParseSxprPCI
- * @root: root sexpr
- *
- * This parses out block devices from the domain sexpr
- *
- * Returns 0 if successful or -1 if failed.
- */
-static int
-xenDaemonParseSxprPCI(virDomainDefPtr def,
-                      const struct sexpr *root)
-{
-    const struct sexpr *cur, *tmp = NULL, *node;
-    virDomainHostdevDefPtr dev = NULL;
-
-    /*
-     * With the (domain ...) block we have the following odd setup
-     *
-     * (device
-     *    (pci
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
-     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
-     *    )
-     * )
-     *
-     * Normally there is one (device ...) block per device, but in
-     * wierd world of Xen PCI, once (device ...) covers multiple
-     * devices.
-     */
-
-    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        node = cur->u.s.car;
-        if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
-            break;
-    }
-
-    if (!tmp)
-        return 0;
-
-    for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
-        const char *domain = NULL;
-        const char *bus = NULL;
-        const char *slot = NULL;
-        const char *func = NULL;
-        int domainID;
-        int busID;
-        int slotID;
-        int funcID;
-
-        node = cur->u.s.car;
-        if (!sexpr_lookup(node, "dev"))
-            continue;
-
-        if (!(domain = sexpr_node(node, "dev/domain"))) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI domain"));
-            goto error;
-        }
-        if (!(bus = sexpr_node(node, "dev/bus"))) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI bus"));
-            goto error;
-        }
-        if (!(slot = sexpr_node(node, "dev/slot"))) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI slot"));
-            goto error;
-        }
-        if (!(func = sexpr_node(node, "dev/func"))) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         "%s", _("missing PCI func"));
-            goto error;
-        }
-
-        if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI domain '%s'"), domain);
-            goto error;
-        }
-        if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI bus '%s'"), bus);
-            goto error;
-        }
-        if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI slot '%s'"), slot);
-            goto error;
-        }
-        if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("cannot parse PCI func '%s'"), func);
-            goto error;
-        }
-
-        if (VIR_ALLOC(dev) < 0)
-            goto no_memory;
-
-        dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
-        dev->managed = 0;
-        dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
-        dev->source.subsys.u.pci.domain = domainID;
-        dev->source.subsys.u.pci.bus = busID;
-        dev->source.subsys.u.pci.slot = slotID;
-        dev->source.subsys.u.pci.function = funcID;
-
-        if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
-            goto no_memory;
-        }
-
-        def->hostdevs[def->nhostdevs++] = dev;
-    }
-
-    return 0;
-
-no_memory:
-    virReportOOMError();
-
-error:
-    virDomainHostdevDefFree(dev);
-    return -1;
-}
-
-
-/**
- * xenDaemonParseSxpr:
- * @conn: the connection associated with the XML
- * @root: the root of the parsed S-Expression
- * @xendConfigVersion: version of xend
- * @cpus: set of cpus the domain may be pinned to
- *
- * Parse the xend sexp description and turn it into the XML format similar
- * to the one unsed for creation.
- *
- * Returns the 0 terminated XML string or NULL in case of error.
- *         the caller must free() the returned value.
- */
-static virDomainDefPtr
-xenDaemonParseSxpr(virConnectPtr conn,
-                   const struct sexpr *root,
-                   int xendConfigVersion,
-                   const char *cpus)
-{
-    xenUnifiedPrivatePtr priv = conn->privateData;
-    const char *tmp;
-    virDomainDefPtr def;
-    int hvm = 0;
-    char *tty = NULL;
-
-    if (VIR_ALLOC(def) < 0)
-        goto no_memory;
-
-    tmp = sexpr_node(root, "domain/domid");
-    if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing id"));
-        goto error;
-    }
-    def->virtType = VIR_DOMAIN_VIRT_XEN;
-    if (tmp)
-        def->id = sexpr_int(root, "domain/domid");
-    else
-        def->id = -1;
-
-    if (sexpr_node_copy(root, "domain/name", &def->name) < 0)
-        goto no_memory;
-    if (def->name == NULL) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing name"));
-        goto error;
-    }
-
-    tmp = sexpr_node(root, "domain/uuid");
-    if (tmp == NULL) {
-        virXendError(VIR_ERR_INTERNAL_ERROR,
-                     "%s", _("domain information incomplete, missing name"));
-        goto error;
-    }
-    virUUIDParse(tmp, def->uuid);
-
-    if (sexpr_node_copy(root, "domain/description", &def->description) < 0)
-        goto no_memory;
-
-    hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
-    if (!hvm) {
-        if (sexpr_node_copy(root, "domain/bootloader",
-                            &def->os.bootloader) < 0)
-            goto no_memory;
-
-        if (!def->os.bootloader &&
-            sexpr_has(root, "domain/bootloader") &&
-            (def->os.bootloader = strdup("")) == NULL)
-            goto no_memory;
-
-        if (def->os.bootloader &&
-            sexpr_node_copy(root, "domain/bootloader_args",
-                            &def->os.bootloaderArgs) < 0)
-            goto no_memory;
-    }
-
-    if (!(def->os.type = strdup(hvm ? "hvm" : "linux")))
-        goto no_memory;
-
-    if (def->id != 0) {
-        if (sexpr_lookup(root, "domain/image")) {
-            if (xenDaemonParseSxprOS(root, def, hvm) < 0)
-                goto error;
-        }
-    }
-
-    def->mem.max_balloon = (unsigned long)
-                           (sexpr_u64(root, "domain/maxmem") << 10);
-    def->mem.cur_balloon = (unsigned long)
-                           (sexpr_u64(root, "domain/memory") << 10);
-    if (def->mem.cur_balloon > def->mem.max_balloon)
-        def->mem.cur_balloon = def->mem.max_balloon;
-
-    if (cpus != NULL) {
-        def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
-        if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
-            virReportOOMError();
-            goto error;
-        }
-
-        if (virDomainCpuSetParse(&cpus,
-                                 0, def->cpumask,
-                                 def->cpumasklen) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("invalid CPU mask %s"), cpus);
-            goto error;
-        }
-    }
-
-    def->maxvcpus = sexpr_int(root, "domain/vcpus");
-    def->vcpus = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail"));
-    if (!def->vcpus || def->maxvcpus < def->vcpus)
-        def->vcpus = def->maxvcpus;
-
-    tmp = sexpr_node(root, "domain/on_poweroff");
-    if (tmp != NULL) {
-        if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("unknown lifecycle type %s"), tmp);
-            goto error;
-        }
-    } else
-        def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
-
-    tmp = sexpr_node(root, "domain/on_reboot");
-    if (tmp != NULL) {
-        if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("unknown lifecycle type %s"), tmp);
-            goto error;
-        }
-    } else
-        def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
-
-    tmp = sexpr_node(root, "domain/on_crash");
-    if (tmp != NULL) {
-        if ((def->onCrash = virDomainLifecycleCrashTypeFromString(tmp)) < 0) {
-            virXendError(VIR_ERR_INTERNAL_ERROR,
-                         _("unknown lifecycle type %s"), tmp);
-            goto error;
-        }
-    } else
-        def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
-
-    def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
-    if (hvm) {
-        if (sexpr_int(root, "domain/image/hvm/acpi"))
-            def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
-        if (sexpr_int(root, "domain/image/hvm/apic"))
-            def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
-        if (sexpr_int(root, "domain/image/hvm/pae"))
-            def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
-        if (sexpr_int(root, "domain/image/hvm/hap"))
-            def->features |= (1 << VIR_DOMAIN_FEATURE_HAP);
-
-        /* Old XenD only allows localtime here for HVM */
-        if (sexpr_int(root, "domain/image/hvm/localtime"))
-            def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
-    }
-
-    /* Current XenD allows localtime here, for PV and HVM */
-    if (sexpr_int(root, "domain/localtime"))
-        def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
-
-    if (sexpr_node_copy(root, hvm ?
-                        "domain/image/hvm/device_model" :
-                        "domain/image/linux/device_model",
-                        &def->emulator) < 0)
-        goto no_memory;
-
-    /* append block devices */
-    if (xenDaemonParseSxprDisks(def, root, hvm, xendConfigVersion) < 0)
-        goto error;
-
-    if (xenDaemonParseSxprNets(def, root) < 0)
-        goto error;
-
-    if (xenDaemonParseSxprPCI(def, root) < 0)
-        goto error;
-
-    /* New style graphics device config */
-    if (xenDaemonParseSxprGraphicsNew(conn, def, root) < 0)
-        goto error;
-
-    /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
-    if ((def->ngraphics == 0) &&
-        xenDaemonParseSxprGraphicsOld(conn, def, root, hvm, xendConfigVersion) < 0)
-        goto error;
-
-
-    /* Old style cdrom config from Xen <= 3.0.2 */
-    if (hvm &&
-        xendConfigVersion == 1) {
-        tmp = sexpr_node(root, "domain/image/hvm/cdrom");
-        if ((tmp != NULL) && (tmp[0] != 0)) {
-            virDomainDiskDefPtr disk;
-            if (VIR_ALLOC(disk) < 0)
-                goto no_memory;
-            if (!(disk->src = strdup(tmp))) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
-            if (!(disk->dst = strdup("hdc"))) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            if (!(disk->driverName = strdup("file"))) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
-            disk->readonly = 1;
-
-            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
-                virDomainDiskDefFree(disk);
-                goto no_memory;
-            }
-            def->disks[def->ndisks++] = disk;
-        }
-    }
-
-
-    /* Floppy disk config */
-    if (hvm) {
-        const char *const fds[] = { "fda", "fdb" };
-        int i;
-        for (i = 0 ; i < ARRAY_CARDINALITY(fds) ; i++) {
-            tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
-            if ((tmp != NULL) && (tmp[0] != 0)) {
-                virDomainDiskDefPtr disk;
-                if (VIR_ALLOC(disk) < 0)
-                    goto no_memory;
-                if (!(disk->src = strdup(tmp))) {
-                    VIR_FREE(disk);
-                    goto no_memory;
-                }
-                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
-                disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
-                if (!(disk->dst = strdup(fds[i]))) {
-                    virDomainDiskDefFree(disk);
-                    goto no_memory;
-                }
-                if (!(disk->driverName = strdup("file"))) {
-                    virDomainDiskDefFree(disk);
-                    goto no_memory;
-                }
-                disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
-
-                if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
-                    virDomainDiskDefFree(disk);
-                    goto no_memory;
-                }
-                def->disks[def->ndisks++] = disk;
-            }
-        }
-    }
-
-    /* in case of HVM we have USB device emulation */
-    if (hvm &&
-        xenDaemonParseSxprUSB(def, root) < 0)
-        goto error;
-
-    /* Character device config */
-    xenUnifiedLock(priv);
-    tty = xenStoreDomainGetConsolePath(conn, def->id);
-    xenUnifiedUnlock(priv);
-    if (hvm) {
-        tmp = sexpr_node(root, "domain/image/hvm/serial");
-        if (tmp && STRNEQ(tmp, "none")) {
-            virDomainChrDefPtr chr;
-            if ((chr = xenDaemonParseSxprChar(tmp, tty)) == NULL)
-                goto error;
-            if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
-                virDomainChrDefFree(chr);
-                goto no_memory;
-            }
-            chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
-            def->serials[def->nserials++] = chr;
-        }
-        tmp = sexpr_node(root, "domain/image/hvm/parallel");
-        if (tmp && STRNEQ(tmp, "none")) {
-            virDomainChrDefPtr chr;
-            /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
-            if ((chr = xenDaemonParseSxprChar(tmp, NULL)) == NULL)
-                goto error;
-            if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
-                virDomainChrDefFree(chr);
-                goto no_memory;
-            }
-            chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
-            def->parallels[def->nparallels++] = chr;
-        }
-    } else {
-        /* Fake a paravirt console, since that's not in the sexpr */
-        if (!(def->console = xenDaemonParseSxprChar("pty", tty)))
-            goto error;
-        def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
-        def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
-    }
-    VIR_FREE(tty);
-
-
-    /* Sound device config */
-    if (hvm &&
-        (tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL &&
-        *tmp) {
-        if (xenDaemonParseSxprSound(def, tmp) < 0)
-            goto error;
-    }
-
-    return def;
-
-no_memory:
-    virReportOOMError();
-error:
-    VIR_FREE(tty);
-    virDomainDefFree(def);
-    return NULL;
-}
-
-virDomainDefPtr
-xenDaemonParseSxprString(virConnectPtr conn,
-                         const char *sexpr,
-                         int xendConfigVersion)
-{
-    struct sexpr *root = string2sexpr(sexpr);
-    virDomainDefPtr def;
-
-    if (!root)
-        return NULL;
-
-    def = xenDaemonParseSxpr(conn, root, xendConfigVersion, NULL);
-
-    sexpr_free(root);
-
-    return def;
-}
-
-
 /**
  * sexpr_to_xend_domain_info:
  * @root: an S-Expression describing a domain
@@ -3098,6 +1798,9 @@ xenDaemonDomainFetch(virConnectPtr conn,
     struct sexpr *root;
     xenUnifiedPrivatePtr priv;
     virDomainDefPtr def;
+    int id;
+    char * tty;
+    int vncport;
 
     if (name)
         root = sexpr_get(conn, "/xend/domain/%s?detail=1", name);
@@ -3112,10 +1815,16 @@ xenDaemonDomainFetch(virConnectPtr conn,
 
     priv = (xenUnifiedPrivatePtr) conn->privateData;
 
-    if (!(def = xenDaemonParseSxpr(conn,
-                                   root,
+    id = xenGetDomIdFromSxpr(root, priv->xendConfigVersion);
+    xenUnifiedLock(priv);
+    tty = xenStoreDomainGetConsolePath(conn, id);
+    vncport = xenStoreDomainGetVNCPort(conn, id);
+    xenUnifiedUnlock(priv);
+    if (!(def = xenDaemonParseSxpr(root,
                                    priv->xendConfigVersion,
-                                   cpus)))
+                                   cpus,
+                                   tty,
+                                   vncport)))
         goto cleanup;
 
 cleanup:
@@ -5043,6 +3752,9 @@ xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
     int fd = -1, ret = -1;
     int found = 0, i;
     virDomainDefPtr def;
+    int id;
+    char * tty;
+    int vncport;
 
     priv = (xenUnifiedPrivatePtr) domain->conn->privateData;
 
@@ -5068,7 +3780,14 @@ xenDaemonDomainBlockPeek (virDomainPtr domain, const char *path,
         return -1;
     }
 
-    if (!(def = xenDaemonParseSxpr(domain->conn, root, priv->xendConfigVersion, NULL)))
+    id = xenGetDomIdFromSxpr(root, priv->xendConfigVersion);
+    xenUnifiedLock(priv);
+    tty = xenStoreDomainGetConsolePath(domain->conn, id);
+    vncport = xenStoreDomainGetVNCPort(domain->conn, id);
+    xenUnifiedUnlock(priv);
+
+    if (!(def = xenDaemonParseSxpr(root, priv->xendConfigVersion, NULL, tty,
+                                   vncport)))
         goto cleanup;
 
     for (i = 0 ; i < def->ndisks ; i++) {
diff --git a/src/xen/xend_internal.h b/src/xen/xend_internal.h
index 53f5d2c..8603a08 100644
--- a/src/xen/xend_internal.h
+++ b/src/xen/xend_internal.h
@@ -27,12 +27,6 @@
 # include "driver.h"
 # include "buf.h"
 
-# ifdef __sun
-#  define DEFAULT_VIF_SCRIPT "vif-vnic"
-# else
-#  define DEFAULT_VIF_SCRIPT "vif-bridge"
-# endif
-
 int
 xenDaemonOpen_unix(virConnectPtr conn, const char *path);
 
@@ -96,18 +90,6 @@ xenDaemonDomainFetch(virConnectPtr xend,
                      const char *name,
                      const char *cpus);
 
-virDomainDefPtr
-xenDaemonParseSxprString(virConnectPtr conn,
-                         const char *sexpr,
-                         int xendConfigVersion);
-
-int
-xenDaemonParseSxprSound(virDomainDefPtr def,
-                        const char *str);
-
-virDomainChrDefPtr
-xenDaemonParseSxprChar(const char *value,
-                       const char *tty);
 
 int
 xenDaemonFormatSxprChr(virDomainChrDefPtr def,
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index 865805c..2991336 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -40,6 +40,7 @@
 #include "xm_internal.h"
 #include "xen_driver.h"
 #include "xend_internal.h"
+#include "xen_sxpr.h"
 #include "hash.h"
 #include "buf.h"
 #include "uuid.h"
diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
new file mode 100644
index 0000000..edd0fb4
--- /dev/null
+++ b/src/xenxs/xen_sxpr.c
@@ -0,0 +1,1351 @@
+/*
+ * xen_sxpr.c: Xen SEXPR parsing functions
+ *
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Anthony Liguori <aliguori@us.ibm.com>
+ * Author: Daniel Veillard <veillard@redhat.com>
+ * Author: Markus Groß <gross@univention.de>
+ */
+
+#include <config.h>
+
+#include "internal.h"
+#include "virterror_internal.h"
+#include "conf.h"
+#include "memory.h"
+#include "verify.h"
+#include "uuid.h"
+#include "logging.h"
+#include "count-one-bits.h"
+#include "xenxs_private.h"
+#include "xen_sxpr.h"
+
+/* Get a domain id from a sexpr string */
+int xenGetDomIdFromSxprString(const char *sexpr, int xendConfigVersion)
+{
+    struct sexpr *root = string2sexpr(sexpr);
+
+    if (!root)
+        return -1;
+
+    int id = xenGetDomIdFromSxpr(root, xendConfigVersion);
+    sexpr_free(root);
+    return id;
+}
+
+/* Get a domain id from a sexpr */
+int xenGetDomIdFromSxpr(const struct sexpr *root, int xendConfigVersion)
+{
+    int id = -1;
+    const char * tmp = sexpr_node(root, "domain/domid");
+    if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing id"));
+    } else {
+      id = tmp ? sexpr_int(root, "domain/domid") : -1;
+    }
+    return id;
+}
+
+/*****************************************************************
+ ******
+ ****** Parsing of SEXPR into virDomainDef objects
+ ******
+ *****************************************************************/
+
+/**
+ * xenDaemonParseSxprOS
+ * @node: the root of the parsed S-Expression
+ * @def: the domain config
+ * @hvm: true or 1 if no contains HVM S-Expression
+ * @bootloader: true or 1 if a bootloader is defined
+ *
+ * Parse the xend sexp for description of os and append it to buf.
+ *
+ * Returns 0 in case of success and -1 in case of error
+ */
+static int
+xenDaemonParseSxprOS(const struct sexpr *node,
+                     virDomainDefPtr def,
+                     int hvm)
+{
+    if (hvm) {
+        if (sexpr_node_copy(node, "domain/image/hvm/loader", &def->os.loader) < 0)
+            goto no_memory;
+        if (def->os.loader == NULL) {
+            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.loader) < 0)
+                goto no_memory;
+
+            if (def->os.loader == NULL) {
+                XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("domain information incomplete, missing HVM loader"));
+                return(-1);
+            }
+        } else {
+            if (sexpr_node_copy(node, "domain/image/hvm/kernel", &def->os.kernel) < 0)
+                goto no_memory;
+            if (sexpr_node_copy(node, "domain/image/hvm/ramdisk", &def->os.initrd) < 0)
+                goto no_memory;
+            if (sexpr_node_copy(node, "domain/image/hvm/args", &def->os.cmdline) < 0)
+                goto no_memory;
+            if (sexpr_node_copy(node, "domain/image/hvm/root", &def->os.root) < 0)
+                goto no_memory;
+        }
+    } else {
+        if (sexpr_node_copy(node, "domain/image/linux/kernel", &def->os.kernel) < 0)
+            goto no_memory;
+        if (sexpr_node_copy(node, "domain/image/linux/ramdisk", &def->os.initrd) < 0)
+            goto no_memory;
+        if (sexpr_node_copy(node, "domain/image/linux/args", &def->os.cmdline) < 0)
+            goto no_memory;
+        if (sexpr_node_copy(node, "domain/image/linux/root", &def->os.root) < 0)
+            goto no_memory;
+    }
+
+    /* If HVM kenrel == loader, then old xend, so kill off kernel */
+    if (hvm &&
+        def->os.kernel &&
+        STREQ(def->os.kernel, def->os.loader)) {
+        VIR_FREE(def->os.kernel);
+    }
+
+    if (!def->os.kernel &&
+        hvm) {
+        const char *boot = sexpr_node(node, "domain/image/hvm/boot");
+        if ((boot != NULL) && (boot[0] != 0)) {
+            while (*boot &&
+                   def->os.nBootDevs < VIR_DOMAIN_BOOT_LAST) {
+                if (*boot == 'a')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_FLOPPY;
+                else if (*boot == 'c')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_DISK;
+                else if (*boot == 'd')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_CDROM;
+                else if (*boot == 'n')
+                    def->os.bootDevs[def->os.nBootDevs++] = VIR_DOMAIN_BOOT_NET;
+                boot++;
+            }
+        }
+    }
+
+    if (!hvm &&
+        !def->os.kernel &&
+        !def->os.bootloader) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing kernel & bootloader"));
+        return -1;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+    return -1;
+}
+
+virDomainChrDefPtr
+xenDaemonParseSxprChar(const char *value,
+                       const char *tty)
+{
+    const char *prefix;
+    char *tmp;
+    virDomainChrDefPtr def;
+
+    if (VIR_ALLOC(def) < 0) {
+        virReportOOMError();
+        return NULL;
+    }
+
+    prefix = value;
+
+    if (value[0] == '/') {
+        def->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
+    } else {
+        if ((tmp = strchr(value, ':')) != NULL) {
+            *tmp = '\0';
+            value = tmp + 1;
+        }
+
+        if (STRPREFIX(prefix, "telnet")) {
+            def->source.type = VIR_DOMAIN_CHR_TYPE_TCP;
+            def->source.data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
+        } else {
+            if ((def->source.type = virDomainChrTypeFromString(prefix)) < 0) {
+                XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             _("unknown chr device type '%s'"), prefix);
+                goto error;
+            }
+        }
+    }
+
+    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
+    switch (def->source.type) {
+    case VIR_DOMAIN_CHR_TYPE_PTY:
+        if (tty != NULL &&
+            !(def->source.data.file.path = strdup(tty)))
+            goto no_memory;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_FILE:
+    case VIR_DOMAIN_CHR_TYPE_PIPE:
+        if (!(def->source.data.file.path = strdup(value)))
+            goto no_memory;
+        break;
+
+    case VIR_DOMAIN_CHR_TYPE_TCP:
+    {
+        const char *offset = strchr(value, ':');
+        const char *offset2;
+
+        if (offset == NULL) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            (def->source.data.tcp.host = strndup(value,
+                                                 offset - value)) == NULL)
+            goto no_memory;
+
+        offset2 = strchr(offset, ',');
+        if (offset2 == NULL)
+            def->source.data.tcp.service = strdup(offset+1);
+        else
+            def->source.data.tcp.service = strndup(offset+1,
+                                                   offset2-(offset+1));
+        if (def->source.data.tcp.service == NULL)
+            goto no_memory;
+
+        if (offset2 && strstr(offset2, ",server"))
+            def->source.data.tcp.listen = true;
+    }
+    break;
+
+    case VIR_DOMAIN_CHR_TYPE_UDP:
+    {
+        const char *offset = strchr(value, ':');
+        const char *offset2, *offset3;
+
+        if (offset == NULL) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("malformed char device string"));
+            goto error;
+        }
+
+        if (offset != value &&
+            (def->source.data.udp.connectHost
+             = strndup(value, offset - value)) == NULL)
+            goto no_memory;
+
+        offset2 = strchr(offset, '@');
+        if (offset2 != NULL) {
+            if ((def->source.data.udp.connectService
+                 = strndup(offset + 1, offset2-(offset+1))) == NULL)
+                goto no_memory;
+
+            offset3 = strchr(offset2, ':');
+            if (offset3 == NULL) {
+                XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("malformed char device string"));
+                goto error;
+            }
+
+            if (offset3 > (offset2 + 1) &&
+                (def->source.data.udp.bindHost
+                 = strndup(offset2 + 1, offset3 - (offset2+1))) == NULL)
+                goto no_memory;
+
+            if ((def->source.data.udp.bindService
+                 = strdup(offset3 + 1)) == NULL)
+                goto no_memory;
+        } else {
+            if ((def->source.data.udp.connectService
+                 = strdup(offset + 1)) == NULL)
+                goto no_memory;
+        }
+    }
+    break;
+
+    case VIR_DOMAIN_CHR_TYPE_UNIX:
+    {
+        const char *offset = strchr(value, ',');
+        if (offset)
+            def->source.data.nix.path = strndup(value, (offset - value));
+        else
+            def->source.data.nix.path = strdup(value);
+        if (def->source.data.nix.path == NULL)
+            goto no_memory;
+
+        if (offset != NULL &&
+            strstr(offset, ",server") != NULL)
+            def->source.data.nix.listen = true;
+    }
+    break;
+    }
+
+    return def;
+
+no_memory:
+    virReportOOMError();
+error:
+    virDomainChrDefFree(def);
+    return NULL;
+}
+
+/**
+ * xend_parse_sexp_desc_disks
+ * @conn: connection
+ * @root: root sexpr
+ * @xendConfigVersion: version of xend
+ *
+ * This parses out block devices from the domain sexpr
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenDaemonParseSxprDisks(virDomainDefPtr def,
+                        const struct sexpr *root,
+                        int hvm,
+                        int xendConfigVersion)
+{
+    const struct sexpr *cur, *node;
+    virDomainDiskDefPtr disk = NULL;
+
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        /* Normally disks are in a (device (vbd ...)) block
+           but blktap disks ended up in a differently named
+           (device (tap ....)) block.... */
+        if (sexpr_lookup(node, "device/vbd") ||
+            sexpr_lookup(node, "device/tap") ||
+            sexpr_lookup(node, "device/tap2")) {
+            char *offset;
+            const char *src = NULL;
+            const char *dst = NULL;
+            const char *mode = NULL;
+
+            /* Again dealing with (vbd...) vs (tap ...) differences */
+            if (sexpr_lookup(node, "device/vbd")) {
+                src = sexpr_node(node, "device/vbd/uname");
+                dst = sexpr_node(node, "device/vbd/dev");
+                mode = sexpr_node(node, "device/vbd/mode");
+            } else if (sexpr_lookup(node, "device/tap2")) {
+                src = sexpr_node(node, "device/tap2/uname");
+                dst = sexpr_node(node, "device/tap2/dev");
+                mode = sexpr_node(node, "device/tap2/mode");
+            } else {
+                src = sexpr_node(node, "device/tap/uname");
+                dst = sexpr_node(node, "device/tap/dev");
+                mode = sexpr_node(node, "device/tap/mode");
+            }
+
+            if (VIR_ALLOC(disk) < 0)
+                goto no_memory;
+
+            if (dst == NULL) {
+                XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("domain information incomplete, vbd has no dev"));
+                goto error;
+            }
+
+            if (src == NULL) {
+                /* There is a case without the uname to the CD-ROM device */
+                offset = strchr(dst, ':');
+                if (!offset ||
+                    !hvm ||
+                    STRNEQ(offset, ":cdrom")) {
+                    XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("domain information incomplete, vbd has no src"));
+                    goto error;
+                }
+            }
+
+            if (src != NULL) {
+                offset = strchr(src, ':');
+                if (!offset) {
+                    XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("cannot parse vbd filename, missing driver name"));
+                    goto error;
+                }
+
+                if (VIR_ALLOC_N(disk->driverName, (offset-src)+1) < 0)
+                    goto no_memory;
+                if (virStrncpy(disk->driverName, src, offset-src,
+                              (offset-src)+1) == NULL) {
+                    XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                                 _("Driver name %s too big for destination"),
+                                 src);
+                    goto error;
+                }
+
+                src = offset + 1;
+
+                if (STREQ (disk->driverName, "tap") ||
+                    STREQ (disk->driverName, "tap2")) {
+                    offset = strchr(src, ':');
+                    if (!offset) {
+                        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                                     "%s", _("cannot parse vbd filename, missing driver type"));
+                        goto error;
+                    }
+
+                    if (VIR_ALLOC_N(disk->driverType, (offset-src)+1)< 0)
+                        goto no_memory;
+                    if (virStrncpy(disk->driverType, src, offset-src,
+                                   (offset-src)+1) == NULL) {
+                        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                                     _("Driver type %s too big for destination"),
+                                     src);
+                        goto error;
+                    }
+
+                    src = offset + 1;
+                    /* Its possible to use blktap driver for block devs
+                       too, but kinda pointless because blkback is better,
+                       so we assume common case here. If blktap becomes
+                       omnipotent, we can revisit this, perhaps stat()'ing
+                       the src file in question */
+                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+                } else if (STREQ(disk->driverName, "phy")) {
+                    disk->type = VIR_DOMAIN_DISK_TYPE_BLOCK;
+                } else if (STREQ(disk->driverName, "file")) {
+                    disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+                }
+            } else {
+                /* No CDROM media so can't really tell. We'll just
+                   call if a FILE for now and update when media
+                   is inserted later */
+                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            }
+
+            if (STREQLEN (dst, "ioemu:", 6))
+                dst += 6;
+
+            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
+            /* New style disk config from Xen >= 3.0.3 */
+            if (xendConfigVersion > 1) {
+                offset = strrchr(dst, ':');
+                if (offset) {
+                    if (STREQ (offset, ":cdrom")) {
+                        disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+                    } else if (STREQ (offset, ":disk")) {
+                        /* The default anyway */
+                    } else {
+                        /* Unknown, lets pretend its a disk too */
+                    }
+                    offset[0] = '\0';
+                }
+            }
+
+            if (!(disk->dst = strdup(dst)))
+                goto no_memory;
+            if (src &&
+                !(disk->src = strdup(src)))
+                goto no_memory;
+
+            if (STRPREFIX(disk->dst, "xvd"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
+            else if (STRPREFIX(disk->dst, "hd"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            else if (STRPREFIX(disk->dst, "sd"))
+                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
+            else
+                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+
+            if (mode &&
+                strchr(mode, 'r'))
+                disk->readonly = 1;
+            if (mode &&
+                strchr(mode, '!'))
+                disk->shared = 1;
+
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
+                goto no_memory;
+
+            def->disks[def->ndisks++] = disk;
+            disk = NULL;
+        }
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+
+error:
+    virDomainDiskDefFree(disk);
+    return -1;
+}
+
+
+static int
+xenDaemonParseSxprNets(virDomainDefPtr def,
+                       const struct sexpr *root)
+{
+    virDomainNetDefPtr net = NULL;
+    const struct sexpr *cur, *node;
+    const char *tmp;
+    int vif_index = 0;
+
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if (sexpr_lookup(node, "device/vif")) {
+            const char *tmp2, *model, *type;
+            char buf[50];
+            tmp2 = sexpr_node(node, "device/vif/script");
+            tmp = sexpr_node(node, "device/vif/bridge");
+            model = sexpr_node(node, "device/vif/model");
+            type = sexpr_node(node, "device/vif/type");
+
+            if (VIR_ALLOC(net) < 0)
+                goto no_memory;
+
+            if (tmp != NULL ||
+                (tmp2 != NULL && STREQ(tmp2, DEFAULT_VIF_SCRIPT))) {
+                net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+                /* XXX virtual network reverse resolve */
+
+                if (tmp &&
+                    !(net->data.bridge.brname = strdup(tmp)))
+                    goto no_memory;
+                if (tmp2 &&
+                    net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
+                    !(net->data.bridge.script = strdup(tmp2)))
+                    goto no_memory;
+                tmp = sexpr_node(node, "device/vif/ip");
+                if (tmp &&
+                    !(net->data.bridge.ipaddr = strdup(tmp)))
+                    goto no_memory;
+            } else {
+                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
+                if (tmp2 &&
+                    !(net->data.ethernet.script = strdup(tmp2)))
+                    goto no_memory;
+                tmp = sexpr_node(node, "device/vif/ip");
+                if (tmp &&
+                    !(net->data.ethernet.ipaddr = strdup(tmp)))
+                    goto no_memory;
+            }
+
+            tmp = sexpr_node(node, "device/vif/vifname");
+            if (!tmp) {
+                snprintf(buf, sizeof(buf), "vif%d.%d", def->id, vif_index);
+                tmp = buf;
+            }
+            if (!(net->ifname = strdup(tmp)))
+                goto no_memory;
+
+            tmp = sexpr_node(node, "device/vif/mac");
+            if (tmp) {
+                if (virParseMacAddr(tmp, net->mac) < 0) {
+                    XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                                 _("malformed mac address '%s'"), tmp);
+                    goto cleanup;
+                }
+            }
+
+            if (model &&
+                !(net->model = strdup(model)))
+                goto no_memory;
+
+            if (!model && type &&
+                STREQ(type, "netfront") &&
+                !(net->model = strdup("netfront")))
+                goto no_memory;
+
+            if (VIR_REALLOC_N(def->nets, def->nnets + 1) < 0)
+                goto no_memory;
+
+            def->nets[def->nnets++] = net;
+            vif_index++;
+        }
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+cleanup:
+    virDomainNetDefFree(net);
+    return -1;
+}
+
+
+int
+xenDaemonParseSxprSound(virDomainDefPtr def,
+                        const char *str)
+{
+    if (STREQ(str, "all")) {
+        int i;
+
+        /*
+         * Special compatability code for Xen with a bogus
+         * sound=all in config.
+         *
+         * NB delibrately, don't include all possible
+         * sound models anymore, just the 2 that were
+         * historically present in Xen's QEMU.
+         *
+         * ie just es1370 + sb16.
+         *
+         * Hence use of MODEL_ES1370 + 1, instead of MODEL_LAST
+         */
+
+        if (VIR_ALLOC_N(def->sounds,
+                        VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) < 0)
+            goto no_memory;
+
+
+        for (i = 0 ; i < (VIR_DOMAIN_SOUND_MODEL_ES1370 + 1) ; i++) {
+            virDomainSoundDefPtr sound;
+            if (VIR_ALLOC(sound) < 0)
+                goto no_memory;
+            sound->model = i;
+            def->sounds[def->nsounds++] = sound;
+        }
+    } else {
+        char model[10];
+        const char *offset = str, *offset2;
+
+        do {
+            int len;
+            virDomainSoundDefPtr sound;
+            offset2 = strchr(offset, ',');
+            if (offset2)
+                len = (offset2 - offset);
+            else
+                len = strlen(offset);
+            if (virStrncpy(model, offset, len, sizeof(model)) == NULL) {
+                XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                                 _("Sound model %s too big for destination"),
+                             offset);
+                goto error;
+            }
+
+            if (VIR_ALLOC(sound) < 0)
+                goto no_memory;
+
+            if ((sound->model = virDomainSoundModelTypeFromString(model)) < 0) {
+                VIR_FREE(sound);
+                goto error;
+            }
+
+            if (VIR_REALLOC_N(def->sounds, def->nsounds+1) < 0) {
+                virDomainSoundDefFree(sound);
+                goto no_memory;
+            }
+
+            def->sounds[def->nsounds++] = sound;
+            offset = offset2 ? offset2 + 1 : NULL;
+        } while (offset);
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+error:
+    return -1;
+}
+
+
+static int
+xenDaemonParseSxprUSB(virDomainDefPtr def,
+                      const struct sexpr *root)
+{
+    struct sexpr *cur, *node;
+    const char *tmp;
+
+    for (cur = sexpr_lookup(root, "domain/image/hvm"); cur && cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if (sexpr_lookup(node, "usbdevice")) {
+            tmp = sexpr_node(node, "usbdevice");
+            if (tmp && *tmp) {
+                if (STREQ(tmp, "tablet") ||
+                    STREQ(tmp, "mouse")) {
+                    virDomainInputDefPtr input;
+                    if (VIR_ALLOC(input) < 0)
+                        goto no_memory;
+                    input->bus = VIR_DOMAIN_INPUT_BUS_USB;
+                    if (STREQ(tmp, "tablet"))
+                        input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
+                    else
+                        input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
+
+                    if (VIR_REALLOC_N(def->inputs, def->ninputs+1) < 0) {
+                        VIR_FREE(input);
+                        goto no_memory;
+                    }
+                    def->inputs[def->ninputs++] = input;
+                } else {
+                    /* XXX Handle other non-input USB devices later */
+                }
+            }
+        }
+    }
+    return 0;
+
+no_memory:
+    virReportOOMError();
+    return -1;
+}
+
+static int
+xenDaemonParseSxprGraphicsOld(virDomainDefPtr def,
+                              const struct sexpr *root,
+                              int hvm,
+                              int xendConfigVersion, int vncport)
+{
+    const char *tmp;
+    virDomainGraphicsDefPtr graphics = NULL;
+
+    if ((tmp = sexpr_fmt_node(root, "domain/image/%s/vnc", hvm ? "hvm" : "linux")) &&
+        tmp[0] == '1') {
+        /* Graphics device (HVM, or old (pre-3.0.4) style PV VNC config) */
+        int port;
+        const char *listenAddr = sexpr_fmt_node(root, "domain/image/%s/vnclisten", hvm ? "hvm" : "linux");
+        const char *vncPasswd = sexpr_fmt_node(root, "domain/image/%s/vncpasswd", hvm ? "hvm" : "linux");
+        const char *keymap = sexpr_fmt_node(root, "domain/image/%s/keymap", hvm ? "hvm" : "linux");
+        const char *unused = sexpr_fmt_node(root, "domain/image/%s/vncunused", hvm ? "hvm" : "linux");
+
+        port = vncport;
+
+        if (VIR_ALLOC(graphics) < 0)
+            goto no_memory;
+
+        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
+        /* For Xen >= 3.0.3, don't generate a fixed port mapping
+         * because it will almost certainly be wrong ! Just leave
+         * it as -1 which lets caller see that the VNC server isn't
+         * present yet. Subsquent dumps of the XML will eventually
+         * find the port in XenStore once VNC server has started
+         */
+        if (port == -1 && xendConfigVersion < 2)
+            port = 5900 + def->id;
+
+        if ((unused && STREQ(unused, "1")) || port == -1)
+            graphics->data.vnc.autoport = 1;
+        graphics->data.vnc.port = port;
+
+        if (listenAddr &&
+            !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
+            goto no_memory;
+
+        if (vncPasswd &&
+            !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
+            goto no_memory;
+
+        if (keymap &&
+            !(graphics->data.vnc.keymap = strdup(keymap)))
+            goto no_memory;
+
+        if (VIR_ALLOC_N(def->graphics, 1) < 0)
+            goto no_memory;
+        def->graphics[0] = graphics;
+        def->ngraphics = 1;
+        graphics = NULL;
+    } else if ((tmp = sexpr_fmt_node(root, "domain/image/%s/sdl", hvm ? "hvm" : "linux")) &&
+               tmp[0] == '1') {
+        /* Graphics device (HVM, or old (pre-3.0.4) style PV sdl config) */
+        const char *display = sexpr_fmt_node(root, "domain/image/%s/display", hvm ? "hvm" : "linux");
+        const char *xauth = sexpr_fmt_node(root, "domain/image/%s/xauthority", hvm ? "hvm" : "linux");
+
+        if (VIR_ALLOC(graphics) < 0)
+            goto no_memory;
+
+        graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
+        if (display &&
+            !(graphics->data.sdl.display = strdup(display)))
+            goto no_memory;
+        if (xauth &&
+            !(graphics->data.sdl.xauth = strdup(xauth)))
+            goto no_memory;
+
+        if (VIR_ALLOC_N(def->graphics, 1) < 0)
+            goto no_memory;
+        def->graphics[0] = graphics;
+        def->ngraphics = 1;
+        graphics = NULL;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+    virDomainGraphicsDefFree(graphics);
+    return -1;
+}
+
+
+static int
+xenDaemonParseSxprGraphicsNew(virDomainDefPtr def,
+                              const struct sexpr *root, int vncport)
+{
+    virDomainGraphicsDefPtr graphics = NULL;
+    const struct sexpr *cur, *node;
+    const char *tmp;
+
+    /* append network devices and framebuffer */
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if (sexpr_lookup(node, "device/vfb")) {
+            /* New style graphics config for PV guests in >= 3.0.4,
+             * or for HVM guests in >= 3.0.5 */
+            if (sexpr_node(node, "device/vfb/type")) {
+                tmp = sexpr_node(node, "device/vfb/type");
+            } else if (sexpr_node(node, "device/vfb/vnc")) {
+                tmp = "vnc";
+            } else if (sexpr_node(node, "device/vfb/sdl")) {
+                tmp = "sdl";
+            } else {
+                tmp = "unknown";
+            }
+
+            if (VIR_ALLOC(graphics) < 0)
+                goto no_memory;
+
+            if ((graphics->type = virDomainGraphicsTypeFromString(tmp)) < 0) {
+                XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                             _("unknown graphics type '%s'"), tmp);
+                goto error;
+            }
+
+            if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
+                const char *display = sexpr_node(node, "device/vfb/display");
+                const char *xauth = sexpr_node(node, "device/vfb/xauthority");
+                if (display &&
+                    !(graphics->data.sdl.display = strdup(display)))
+                    goto no_memory;
+                if (xauth &&
+                    !(graphics->data.sdl.xauth = strdup(xauth)))
+                    goto no_memory;
+            } else {
+                int port;
+                const char *listenAddr = sexpr_node(node, "device/vfb/vnclisten");
+                const char *vncPasswd = sexpr_node(node, "device/vfb/vncpasswd");
+                const char *keymap = sexpr_node(node, "device/vfb/keymap");
+                const char *unused = sexpr_node(node, "device/vfb/vncunused");
+
+                port = vncport;
+
+                /* Didn't find port entry in xenstore */
+                if (port == -1) {
+                    const char *str = sexpr_node(node, "device/vfb/vncdisplay");
+                    int val;
+                    if (str != NULL && virStrToLong_i(str, NULL, 0, &val) == 0)
+                        port = val;
+                }
+
+                if ((unused && STREQ(unused, "1")) || port == -1)
+                    graphics->data.vnc.autoport = 1;
+
+                if (port >= 0 && port < 5900)
+                    port += 5900;
+                graphics->data.vnc.port = port;
+
+                if (listenAddr &&
+                    !(graphics->data.vnc.listenAddr = strdup(listenAddr)))
+                    goto no_memory;
+
+                if (vncPasswd &&
+                    !(graphics->data.vnc.auth.passwd = strdup(vncPasswd)))
+                    goto no_memory;
+
+                if (keymap &&
+                    !(graphics->data.vnc.keymap = strdup(keymap)))
+                    goto no_memory;
+            }
+
+            if (VIR_ALLOC_N(def->graphics, 1) < 0)
+                goto no_memory;
+            def->graphics[0] = graphics;
+            def->ngraphics = 1;
+            graphics = NULL;
+            break;
+        }
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+error:
+    virDomainGraphicsDefFree(graphics);
+    return -1;
+}
+
+/**
+ * xenDaemonParseSxprPCI
+ * @root: root sexpr
+ *
+ * This parses out block devices from the domain sexpr
+ *
+ * Returns 0 if successful or -1 if failed.
+ */
+static int
+xenDaemonParseSxprPCI(virDomainDefPtr def,
+                      const struct sexpr *root)
+{
+    const struct sexpr *cur, *tmp = NULL, *node;
+    virDomainHostdevDefPtr dev = NULL;
+
+    /*
+     * With the (domain ...) block we have the following odd setup
+     *
+     * (device
+     *    (pci
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x1b) (func 0x0))
+     *       (dev (domain 0x0000) (bus 0x00) (slot 0x13) (func 0x0))
+     *    )
+     * )
+     *
+     * Normally there is one (device ...) block per device, but in
+     * wierd world of Xen PCI, once (device ...) covers multiple
+     * devices.
+     */
+
+    for (cur = root; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        node = cur->u.s.car;
+        if ((tmp = sexpr_lookup(node, "device/pci")) != NULL)
+            break;
+    }
+
+    if (!tmp)
+        return 0;
+
+    for (cur = tmp; cur->kind == SEXPR_CONS; cur = cur->u.s.cdr) {
+        const char *domain = NULL;
+        const char *bus = NULL;
+        const char *slot = NULL;
+        const char *func = NULL;
+        int domainID;
+        int busID;
+        int slotID;
+        int funcID;
+
+        node = cur->u.s.car;
+        if (!sexpr_lookup(node, "dev"))
+            continue;
+
+        if (!(domain = sexpr_node(node, "dev/domain"))) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI domain"));
+            goto error;
+        }
+        if (!(bus = sexpr_node(node, "dev/bus"))) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI bus"));
+            goto error;
+        }
+        if (!(slot = sexpr_node(node, "dev/slot"))) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI slot"));
+            goto error;
+        }
+        if (!(func = sexpr_node(node, "dev/func"))) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         "%s", _("missing PCI func"));
+            goto error;
+        }
+
+        if (virStrToLong_i(domain, NULL, 0, &domainID) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI domain '%s'"), domain);
+            goto error;
+        }
+        if (virStrToLong_i(bus, NULL, 0, &busID) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI bus '%s'"), bus);
+            goto error;
+        }
+        if (virStrToLong_i(slot, NULL, 0, &slotID) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI slot '%s'"), slot);
+            goto error;
+        }
+        if (virStrToLong_i(func, NULL, 0, &funcID) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("cannot parse PCI func '%s'"), func);
+            goto error;
+        }
+
+        if (VIR_ALLOC(dev) < 0)
+            goto no_memory;
+
+        dev->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
+        dev->managed = 0;
+        dev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
+        dev->source.subsys.u.pci.domain = domainID;
+        dev->source.subsys.u.pci.bus = busID;
+        dev->source.subsys.u.pci.slot = slotID;
+        dev->source.subsys.u.pci.function = funcID;
+
+        if (VIR_REALLOC_N(def->hostdevs, def->nhostdevs+1) < 0) {
+            goto no_memory;
+        }
+
+        def->hostdevs[def->nhostdevs++] = dev;
+    }
+
+    return 0;
+
+no_memory:
+    virReportOOMError();
+
+error:
+    virDomainHostdevDefFree(dev);
+    return -1;
+}
+
+
+/**
+ * xenDaemonParseSxpr:
+ * @conn: the connection associated with the XML
+ * @root: the root of the parsed S-Expression
+ * @xendConfigVersion: version of xend
+ * @cpus: set of cpus the domain may be pinned to
+ *
+ * Parse the xend sexp description and turn it into the XML format similar
+ * to the one unsed for creation.
+ *
+ * Returns the 0 terminated XML string or NULL in case of error.
+ *         the caller must free() the returned value.
+ */
+virDomainDefPtr
+xenDaemonParseSxpr(const struct sexpr *root,
+                   int xendConfigVersion,
+                   const char *cpus, char *tty, int vncport)
+{
+    const char *tmp;
+    virDomainDefPtr def;
+    int hvm = 0;
+
+    if (VIR_ALLOC(def) < 0)
+        goto no_memory;
+
+    tmp = sexpr_node(root, "domain/domid");
+    if (tmp == NULL && xendConfigVersion < 3) { /* Old XenD, domid was mandatory */
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing id"));
+        goto error;
+    }
+    def->virtType = VIR_DOMAIN_VIRT_XEN;
+    if (tmp)
+        def->id = sexpr_int(root, "domain/domid");
+    else
+        def->id = -1;
+
+    if (sexpr_node_copy(root, "domain/name", &def->name) < 0)
+        goto no_memory;
+    if (def->name == NULL) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing name"));
+        goto error;
+    }
+
+    tmp = sexpr_node(root, "domain/uuid");
+    if (tmp == NULL) {
+        XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                     "%s", _("domain information incomplete, missing name"));
+        goto error;
+    }
+    virUUIDParse(tmp, def->uuid);
+
+    if (sexpr_node_copy(root, "domain/description", &def->description) < 0)
+        goto no_memory;
+
+    hvm = sexpr_lookup(root, "domain/image/hvm") ? 1 : 0;
+    if (!hvm) {
+        if (sexpr_node_copy(root, "domain/bootloader",
+                            &def->os.bootloader) < 0)
+            goto no_memory;
+
+        if (!def->os.bootloader &&
+            sexpr_has(root, "domain/bootloader") &&
+            (def->os.bootloader = strdup("")) == NULL)
+            goto no_memory;
+
+        if (def->os.bootloader &&
+            sexpr_node_copy(root, "domain/bootloader_args",
+                            &def->os.bootloaderArgs) < 0)
+            goto no_memory;
+    }
+
+    if (!(def->os.type = strdup(hvm ? "hvm" : "linux")))
+        goto no_memory;
+
+    if (def->id != 0) {
+        if (sexpr_lookup(root, "domain/image")) {
+            if (xenDaemonParseSxprOS(root, def, hvm) < 0)
+                goto error;
+        }
+    }
+
+    def->mem.max_balloon = (unsigned long)
+                           (sexpr_u64(root, "domain/maxmem") << 10);
+    def->mem.cur_balloon = (unsigned long)
+                           (sexpr_u64(root, "domain/memory") << 10);
+    if (def->mem.cur_balloon > def->mem.max_balloon)
+        def->mem.cur_balloon = def->mem.max_balloon;
+
+    if (cpus != NULL) {
+        def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
+        if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
+            virReportOOMError();
+            goto error;
+        }
+
+        if (virDomainCpuSetParse(&cpus,
+                                 0, def->cpumask,
+                                 def->cpumasklen) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("invalid CPU mask %s"), cpus);
+            goto error;
+        }
+    }
+
+    def->maxvcpus = sexpr_int(root, "domain/vcpus");
+    def->vcpus = count_one_bits_l(sexpr_u64(root, "domain/vcpu_avail"));
+    if (!def->vcpus || def->maxvcpus < def->vcpus)
+        def->vcpus = def->maxvcpus;
+
+    tmp = sexpr_node(root, "domain/on_poweroff");
+    if (tmp != NULL) {
+        if ((def->onPoweroff = virDomainLifecycleTypeFromString(tmp)) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("unknown lifecycle type %s"), tmp);
+            goto error;
+        }
+    } else
+        def->onPoweroff = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+    tmp = sexpr_node(root, "domain/on_reboot");
+    if (tmp != NULL) {
+        if ((def->onReboot = virDomainLifecycleTypeFromString(tmp)) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("unknown lifecycle type %s"), tmp);
+            goto error;
+        }
+    } else
+        def->onReboot = VIR_DOMAIN_LIFECYCLE_RESTART;
+
+    tmp = sexpr_node(root, "domain/on_crash");
+    if (tmp != NULL) {
+        if ((def->onCrash = virDomainLifecycleCrashTypeFromString(tmp)) < 0) {
+            XENXS_ERROR(VIR_ERR_INTERNAL_ERROR,
+                         _("unknown lifecycle type %s"), tmp);
+            goto error;
+        }
+    } else
+        def->onCrash = VIR_DOMAIN_LIFECYCLE_DESTROY;
+
+    def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
+    if (hvm) {
+        if (sexpr_int(root, "domain/image/hvm/acpi"))
+            def->features |= (1 << VIR_DOMAIN_FEATURE_ACPI);
+        if (sexpr_int(root, "domain/image/hvm/apic"))
+            def->features |= (1 << VIR_DOMAIN_FEATURE_APIC);
+        if (sexpr_int(root, "domain/image/hvm/pae"))
+            def->features |= (1 << VIR_DOMAIN_FEATURE_PAE);
+        if (sexpr_int(root, "domain/image/hvm/hap"))
+            def->features |= (1 << VIR_DOMAIN_FEATURE_HAP);
+
+        /* Old XenD only allows localtime here for HVM */
+        if (sexpr_int(root, "domain/image/hvm/localtime"))
+            def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
+    }
+
+    /* Current XenD allows localtime here, for PV and HVM */
+    if (sexpr_int(root, "domain/localtime"))
+        def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
+
+    if (sexpr_node_copy(root, hvm ?
+                        "domain/image/hvm/device_model" :
+                        "domain/image/linux/device_model",
+                        &def->emulator) < 0)
+        goto no_memory;
+
+    /* append block devices */
+    if (xenDaemonParseSxprDisks(def, root, hvm, xendConfigVersion) < 0)
+        goto error;
+
+    if (xenDaemonParseSxprNets(def, root) < 0)
+        goto error;
+
+    if (xenDaemonParseSxprPCI(def, root) < 0)
+        goto error;
+
+    /* New style graphics device config */
+    if (xenDaemonParseSxprGraphicsNew(def, root, vncport) < 0)
+        goto error;
+
+    /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */
+    if ((def->ngraphics == 0) &&
+        xenDaemonParseSxprGraphicsOld(def, root, hvm, xendConfigVersion,
+                                      vncport) < 0)
+        goto error;
+
+
+    /* Old style cdrom config from Xen <= 3.0.2 */
+    if (hvm &&
+        xendConfigVersion == 1) {
+        tmp = sexpr_node(root, "domain/image/hvm/cdrom");
+        if ((tmp != NULL) && (tmp[0] != 0)) {
+            virDomainDiskDefPtr disk;
+            if (VIR_ALLOC(disk) < 0)
+                goto no_memory;
+            if (!(disk->src = strdup(tmp))) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
+            if (!(disk->dst = strdup("hdc"))) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            if (!(disk->driverName = strdup("file"))) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
+            disk->readonly = 1;
+
+            if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+                virDomainDiskDefFree(disk);
+                goto no_memory;
+            }
+            def->disks[def->ndisks++] = disk;
+        }
+    }
+
+
+    /* Floppy disk config */
+    if (hvm) {
+        const char *const fds[] = { "fda", "fdb" };
+        int i;
+        for (i = 0 ; i < ARRAY_CARDINALITY(fds) ; i++) {
+            tmp = sexpr_fmt_node(root, "domain/image/hvm/%s", fds[i]);
+            if ((tmp != NULL) && (tmp[0] != 0)) {
+                virDomainDiskDefPtr disk;
+                if (VIR_ALLOC(disk) < 0)
+                    goto no_memory;
+                if (!(disk->src = strdup(tmp))) {
+                    VIR_FREE(disk);
+                    goto no_memory;
+                }
+                disk->type = VIR_DOMAIN_DISK_TYPE_FILE;
+                disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY;
+                if (!(disk->dst = strdup(fds[i]))) {
+                    virDomainDiskDefFree(disk);
+                    goto no_memory;
+                }
+                if (!(disk->driverName = strdup("file"))) {
+                    virDomainDiskDefFree(disk);
+                    goto no_memory;
+                }
+                disk->bus = VIR_DOMAIN_DISK_BUS_FDC;
+
+                if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0) {
+                    virDomainDiskDefFree(disk);
+                    goto no_memory;
+                }
+                def->disks[def->ndisks++] = disk;
+            }
+        }
+    }
+
+    /* in case of HVM we have USB device emulation */
+    if (hvm &&
+        xenDaemonParseSxprUSB(def, root) < 0)
+        goto error;
+
+    /* Character device config */
+    if (hvm) {
+        tmp = sexpr_node(root, "domain/image/hvm/serial");
+        if (tmp && STRNEQ(tmp, "none")) {
+            virDomainChrDefPtr chr;
+            if ((chr = xenDaemonParseSxprChar(tmp, tty)) == NULL)
+                goto error;
+            if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
+            def->serials[def->nserials++] = chr;
+        }
+        tmp = sexpr_node(root, "domain/image/hvm/parallel");
+        if (tmp && STRNEQ(tmp, "none")) {
+            virDomainChrDefPtr chr;
+            /* XXX does XenD stuff parallel port tty info into xenstore somewhere ? */
+            if ((chr = xenDaemonParseSxprChar(tmp, NULL)) == NULL)
+                goto error;
+            if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
+                virDomainChrDefFree(chr);
+                goto no_memory;
+            }
+            chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
+            def->parallels[def->nparallels++] = chr;
+        }
+    } else {
+        /* Fake a paravirt console, since that's not in the sexpr */
+        if (!(def->console = xenDaemonParseSxprChar("pty", tty)))
+            goto error;
+        def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
+        def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
+    }
+    VIR_FREE(tty);
+
+
+    /* Sound device config */
+    if (hvm &&
+        (tmp = sexpr_node(root, "domain/image/hvm/soundhw")) != NULL &&
+        *tmp) {
+        if (xenDaemonParseSxprSound(def, tmp) < 0)
+            goto error;
+    }
+
+    return def;
+
+no_memory:
+    virReportOOMError();
+error:
+    VIR_FREE(tty);
+    virDomainDefFree(def);
+    return NULL;
+}
+
+virDomainDefPtr
+xenDaemonParseSxprString(const char *sexpr,
+                         int xendConfigVersion, char *tty, int vncport)
+{
+    struct sexpr *root = string2sexpr(sexpr);
+    virDomainDefPtr def;
+
+    if (!root)
+        return NULL;
+
+    def = xenDaemonParseSxpr(root, xendConfigVersion, NULL, tty, vncport);
+
+    sexpr_free(root);
+
+    return def;
+}
\ No newline at end of file
diff --git a/src/xenxs/xen_sxpr.h b/src/xenxs/xen_sxpr.h
new file mode 100644
index 0000000..c0c6a53
--- /dev/null
+++ b/src/xenxs/xen_sxpr.h
@@ -0,0 +1,62 @@
+/*
+ * xen_sxpr.h: Xen SEXPR parsing functions
+ *
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2006-2008, 2010 Red Hat, Inc.
+ * Copyright (C) 2005,2006
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Anthony Liguori <aliguori@us.ibm.com>
+ * Author: Daniel Veillard <veillard@redhat.com>
+ * Author: Markus Groß <gross@univention.de>
+ */
+
+#ifndef __VIR_XEN_SXPR_H__
+# define __VIR_XEN_SXPR_H__
+
+# include "internal.h"
+# include "conf.h"
+# include "domain_conf.h"
+# include "sexpr.h"
+
+# ifdef __sun
+#  define DEFAULT_VIF_SCRIPT "vif-vnic"
+# else
+#  define DEFAULT_VIF_SCRIPT "vif-bridge"
+# endif
+
+/* helper functions to get the dom id from a sexpr */
+int xenGetDomIdFromSxprString(const char *sexpr, int xendConfigVersion);
+int xenGetDomIdFromSxpr(const struct sexpr *root, int xendConfigVersion);
+
+virDomainDefPtr
+xenDaemonParseSxprString(const char *sexpr,
+                         int xendConfigVersion, char *tty, int vncport);
+
+virDomainDefPtr
+xenDaemonParseSxpr(const struct sexpr *root,
+                   int xendConfigVersion,
+                   const char *cpus, char *tty, int vncport);
+
+int
+xenDaemonParseSxprSound(virDomainDefPtr def,
+                        const char *str);
+
+virDomainChrDefPtr
+xenDaemonParseSxprChar(const char *value,
+                       const char *tty);
+
+#endif /* __VIR_XEN_SXPR_H__ */
diff --git a/src/xenxs/xenxs_private.h b/src/xenxs/xenxs_private.h
new file mode 100644
index 0000000..02fd1a3
--- /dev/null
+++ b/src/xenxs/xenxs_private.h
@@ -0,0 +1,37 @@
+/*
+ * xenxs_private.h: Private definitions for Xen parsing
+ *
+ * Copyright (C) 2011 Univention GmbH
+ * Copyright (C) 2007, 2010 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Author: Richard W.M. Jones <rjones@redhat.com>
+ * Author: Markus Groß <gross@univention.de>
+ */
+
+#ifndef __VIR_XENXS_PRIVATE_H__
+# define __VIR_XENXS_PRIVATE_H__
+
+# include "internal.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+#define XENXS_ERROR(code, ...)                                                \
+    virReportErrorHelper(NULL, VIR_FROM_NONE, code, __FILE__, __FUNCTION__,   \
+                         __LINE__, __VA_ARGS__)
+
+#endif /* __VIR_XENXS_PRIVATE_H__ */
diff --git a/tests/sexpr2xmltest.c b/tests/sexpr2xmltest.c
index f100dd8..cf3e5bc 100644
--- a/tests/sexpr2xmltest.c
+++ b/tests/sexpr2xmltest.c
@@ -9,6 +9,7 @@
 #include "datatypes.h"
 #include "xen/xen_driver.h"
 #include "xen/xend_internal.h"
+#include "xenxs/xen_sxpr.h"
 #include "testutils.h"
 #include "testutilsxen.h"
 
@@ -25,6 +26,9 @@ static int testCompareFiles(const char *xml, const char *sexpr,
   char *gotxml = NULL;
   char *xmlPtr = &(xmlData[0]);
   char *sexprPtr = &(sexprData[0]);
+  int id;
+  char * tty;
+  int vncport;
   int ret = -1;
   virDomainDefPtr def = NULL;
   virConnectPtr conn;
@@ -48,7 +52,14 @@ static int testCompareFiles(const char *xml, const char *sexpr,
   if (virMutexInit(&priv.lock) < 0)
       goto fail;
 
-  if (!(def = xenDaemonParseSxprString(conn, sexprData, xendConfigVersion)))
+  id = xenGetDomIdFromSxprString(sexprData, xendConfigVersion);
+  xenUnifiedLock(&priv);
+  tty = xenStoreDomainGetConsolePath(conn, id);
+  vncport = xenStoreDomainGetVNCPort(conn, id);
+  xenUnifiedUnlock(&priv);
+
+  if (!(def = xenDaemonParseSxprString(sexprData, xendConfigVersion, tty,
+                                       vncport)))
       goto fail;
 
   if (!(gotxml = virDomainDefFormat(def, 0)))
