WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH][RESEND] - add parallel routines to support domain bu

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH][RESEND] - add parallel routines to support domain building via buffers
From: Ben Thomas <bthomas@xxxxxxxxxxxxxxx>
Date: Mon, 13 Feb 2006 17:43:55 -0500
Delivery-date: Tue, 14 Feb 2006 16:28:50 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mozilla Thunderbird 1.0.7-1.1.fc4 (X11/20050929)
This patch adds a parallel set of APIs to the domain builders to
allow images and ramdisks to be passed via buffer, rather than
via file.  This allows usage of the underlying domain building
routines in "file-challenged" enviroments.

Specifically,  xc_linux_build_mem is the buffer oriented version
of the file-oriented xc_linux_build.  Likewise, xc_hvm_build_mem
is the buffer oriented analog of the file based xc_hvm_build.

This patch also implements a suggestion by Mark Williamson to have
the internal APIs always directly use uncompressed buffers.

-b


Signed-off-by: Ben Thomas (bthomas@xxxxxxxxxxxxxxx)
diff -r 1d36cca98fc3 tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c        Fri Feb 10 12:35:19 2006 +0100
+++ b/tools/libxc/xc_hvm_build.c        Mon Feb 13 17:10:05 2006 -0500
@@ -339,24 +339,29 @@ static int setup_guest(int xc_handle,
     return -1;
 }
 
-int xc_hvm_build(int xc_handle,
-                 uint32_t domid,
-                 int memsize,
-                 const char *image_name,
-                 unsigned int control_evtchn,
-                 unsigned int vcpus,
-                unsigned int acpi,
-                 unsigned int apic,
-                 unsigned int store_evtchn,
-                 unsigned long *store_mfn)
+static int xc_hvm_build_internal(int xc_handle,
+                                 uint32_t domid,
+                                 int memsize,
+                                 unsigned char *image,
+                                 unsigned long image_size,
+                                 unsigned int control_evtchn,
+                                 unsigned int vcpus,
+                                 unsigned int acpi,
+                                 unsigned int apic,
+                                 unsigned int store_evtchn,
+                                 unsigned long *store_mfn)
 {
     dom0_op_t launch_op, op;
     int rc, i;
     vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
     unsigned long nr_pages;
-    char         *image = NULL;
-    unsigned long image_size;
     xen_capabilities_info_t xen_caps;
+
+    if ( (image == NULL) || (image_size == 0) )
+    {
+        ERROR("Image required");
+        goto error_out;
+    }
 
     if ( (rc = xc_version(xc_handle, XENVER_capabilities, &xen_caps)) != 0 )
     {
@@ -376,9 +381,6 @@ int xc_hvm_build(int xc_handle,
         PERROR("Could not find total pages for domain");
         goto error_out;
     }
-
-    if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL )
-        goto error_out;
 
     if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
     {
@@ -398,15 +400,13 @@ int xc_hvm_build(int xc_handle,
     memset(ctxt, 0, sizeof(*ctxt));
 
     ctxt->flags = VGCF_HVM_GUEST;
-    if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
+    if ( setup_guest(xc_handle, domid, memsize, (char *)image, image_size, 
nr_pages,
                      ctxt, op.u.getdomaininfo.shared_info_frame, 
control_evtchn,
                      vcpus, acpi, apic, store_evtchn, store_mfn) < 0)
     {
         ERROR("Error constructing guest OS");
         goto error_out;
     }
-
-    free(image);
 
     /* FPU is set up to default initial state. */
     memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
@@ -451,7 +451,6 @@ int xc_hvm_build(int xc_handle,
     return rc;
 
  error_out:
-    free(image);
     return -1;
 }
 
@@ -581,6 +580,92 @@ loadelfimage(
     return 0;
 }
 
+/* xc_hvm_build
+ *
+ * Create a domain for a virtualized Linux, using files/filenames
+ *
+ */
+
+int xc_hvm_build(int xc_handle,
+                 uint32_t domid,
+                 int memsize,
+                 const char *image_name,
+                 unsigned int control_evtchn,
+                 unsigned int vcpus,
+                 unsigned int acpi,
+                 unsigned int apic,
+                 unsigned int store_evtchn,
+                 unsigned long *store_mfn)
+{
+    unsigned char *image;
+    int  sts;
+    long image_size;
+
+    /* Bring uncompressed image into memory */
+
+    if ( (image_name == NULL) ||
+         ((image = (unsigned char *)xc_read_image(image_name, (unsigned long 
*)&image_size)) == NULL ))
+        return -1;
+
+    sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+                                image, image_size,
+                                control_evtchn, vcpus, acpi,
+                                apic, store_evtchn, store_mfn);
+    free(image);
+    return sts;
+}
+
+/* xc_hvm_build_mem
+ *
+ * Create a domain for a virtualized Linux, using buffers
+ *
+ */
+
+int xc_hvm_build_mem(int xc_handle,
+                     uint32_t domid,
+                     int memsize,
+                     unsigned char *image_buffer,
+                     unsigned long image_size,
+                     unsigned int control_evtchn,
+                     unsigned int vcpus,
+                     unsigned int acpi,
+                     unsigned int apic,
+                     unsigned int store_evtchn,
+                     unsigned long *store_mfn)
+{
+    int sts;
+    unsigned long       img_len;
+    unsigned char       *img;
+
+    /* Validate that there is a kernel buffer */
+
+    if ( (image_buffer == NULL) || (image_size == 0) )
+    {
+        ERROR("kernel image buffer not present");
+        return -EINVAL;
+    }
+
+    img = xc_inflate_buffer(image_buffer, image_size, &img_len);
+    if (img == NULL)
+    {
+        ERROR("unable to inflate ram disk buffer");
+        return -1;
+    }
+
+    sts = xc_hvm_build_internal(xc_handle, domid, memsize,
+                                img, img_len,
+                                control_evtchn, vcpus, acpi,
+                                apic, store_evtchn, store_mfn);
+
+    /* xc_inflate_buffer may return the original buffer pointer (for
+       for already inflated buffers), so exercise some care in freeing */
+
+    if ( (img != NULL) && (img != image_buffer) )
+        free(img);
+
+    return sts;
+}
+
 /*
  * Local variables:
  * mode: C
diff -r 1d36cca98fc3 tools/libxc/xc_ia64_stubs.c
--- a/tools/libxc/xc_ia64_stubs.c       Fri Feb 10 12:35:19 2006 +0100
+++ b/tools/libxc/xc_ia64_stubs.c       Mon Feb 13 17:10:05 2006 -0500
@@ -645,7 +645,7 @@ int xc_hvm_build(int xc_handle,
         goto error_out;
     }
 
-    if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL ){
+    if ( (image = xc_read_image(image_name, &image_size)) == NULL ){
         PERROR("Could not read guest firmware image %s",image_name);
         goto error_out;
     }
diff -r 1d36cca98fc3 tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c      Fri Feb 10 12:35:19 2006 +0100
+++ b/tools/libxc/xc_linux_build.c      Mon Feb 13 17:10:05 2006 -0500
@@ -335,8 +335,8 @@ extern unsigned long xc_ia64_fpsr_defaul
 
 static int setup_guest(int xc_handle,
                        uint32_t dom,
-                       char *image, unsigned long image_size,
-                       gzFile initrd_gfd, unsigned long initrd_len,
+                       const unsigned char *image, unsigned long image_size,
+                       unsigned char *initrd, unsigned long initrd_len,
                        unsigned long nr_pages,
                        unsigned long *pvsi, unsigned long *pvke,
                        unsigned long *pvss, vcpu_guest_context_t *ctxt,
@@ -400,23 +400,20 @@ static int setup_guest(int xc_handle,
     (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
                            &dsi);
 
-    /* Load the initial ramdisk image. */
+    /* Load the initial ramdisk image, if present */
     if ( initrd_len != 0 )
     {
-        for ( i = (vinitrd_start - dsi.v_start);
-              i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE )
-        {
-            char page[PAGE_SIZE];
-            if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
+        /* Pages are not contiguous, so do the copy one page at a time */
+
+        for ( i = (vinitrd_start - dsi.v_start), offset = 0; 
+              i < (vinitrd_end - dsi.v_start);
+              i += PAGE_SIZE, offset += PAGE_SIZE )
             {
-                PERROR("Error reading initrd image, could not");
-                goto error_out;
+                xc_copy_to_domain_page(xc_handle, dom,
+                                       page_array[i>>PAGE_SHIFT],
+                                       &initrd[offset]);
             }
-            xc_copy_to_domain_page(xc_handle, dom,
-                                   page_array[i>>PAGE_SHIFT], page);
-        }
-    }
-
+    }
 
     *pvke = dsi.v_kernentry;
 
@@ -474,8 +471,8 @@ static int setup_guest(int xc_handle,
 #else /* x86 */
 static int setup_guest(int xc_handle,
                        uint32_t dom,
-                       char *image, unsigned long image_size,
-                       gzFile initrd_gfd, unsigned long initrd_len,
+                       const unsigned char *image, unsigned long image_size,
+                       unsigned char *initrd, unsigned long initrd_len,
                        unsigned long nr_pages,
                        unsigned long *pvsi, unsigned long *pvke,
                        unsigned long *pvss, vcpu_guest_context_t *ctxt,
@@ -518,13 +515,13 @@ static int setup_guest(int xc_handle,
     unsigned shadow_mode_enabled;
     unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn;
 
-    rc = probeimageformat(image, image_size, &load_funcs);
+    rc = probeimageformat((char *)image, (unsigned long)image_size, 
&load_funcs);
     if ( rc != 0 )
         goto error_out;
 
     memset(&dsi, 0, sizeof(struct domain_setup_info));
 
-    rc = (load_funcs.parseimage)(image, image_size, &dsi);
+    rc = (load_funcs.parseimage)((char *)image, (unsigned long)image_size, 
&dsi);
     if ( rc != 0 )
         goto error_out;
 
@@ -634,24 +631,22 @@ static int setup_guest(int xc_handle,
         goto error_out;
     }
 
-    (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
+    (load_funcs.loadimage)((char *)image, image_size, xc_handle, dom, 
page_array,
                            &dsi);
 
-    /* Load the initial ramdisk image. */
+    /* Load the initial ramdisk image, if present */
     if ( initrd_len != 0 )
     {
-        for ( i = (vinitrd_start - dsi.v_start); 
-              i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE )
-        {
-            char page[PAGE_SIZE];
-            if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
-            {
-                PERROR("Error reading initrd image, could not");
-                goto error_out;
-            }
+        int offset;
+
+        // Pages are not contiguous, so do the inflation a page at a time
+
+        for ( i = (vinitrd_start - dsi.v_start), offset = 0;
+              i < (vinitrd_end - dsi.v_start);
+              i += PAGE_SIZE, offset += PAGE_SIZE )
             xc_copy_to_domain_page(xc_handle, dom,
-                                   page_array[i>>PAGE_SHIFT], page);
-        }
+                                   page_array[i>>PAGE_SHIFT],
+                                   &initrd[offset]);
     }
 
     /* setup page tables */
@@ -865,52 +860,39 @@ static int setup_guest(int xc_handle,
 }
 #endif
 
-int xc_linux_build(int xc_handle,
-                   uint32_t domid,
-                   const char *image_name,
-                   const char *ramdisk_name,
-                   const char *cmdline,
-                   unsigned long flags,
-                   unsigned int store_evtchn,
-                   unsigned long *store_mfn,
-                   unsigned int console_evtchn,
-                   unsigned long *console_mfn)
+/* xc_linux_build_internal
+ *
+ * Common routine to create a domain for a para-virtualized Linux.  Always 
called with
+ * a buffer containing the uncompressed kernel.  The RAMdisk is either a file, 
or a
+ * buffer with the potentially compressed RAMdisk.  Figure out which, and make 
it all
+ * happen.
+ *
+ */
+
+static int xc_linux_build_internal(int xc_handle,
+                                   uint32_t domid,
+                                   const unsigned char *image,
+                                   unsigned long image_size,
+                                   unsigned char *initrd,
+                                   unsigned long initrd_len,
+                                   const char *cmdline,
+                                   unsigned long flags,
+                                   unsigned int store_evtchn,
+                                   unsigned long *store_mfn,
+                                   unsigned int console_evtchn,
+                                   unsigned long *console_mfn)
 {
     dom0_op_t launch_op;
     DECLARE_DOM0_OP;
-    int initrd_fd = -1;
-    gzFile initrd_gfd = NULL;
     int rc, i;
     vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
     unsigned long nr_pages;
-    char         *image = NULL;
-    unsigned long image_size, initrd_size=0;
     unsigned long vstartinfo_start, vkern_entry, vstack_start;
 
     if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 )
     {
         PERROR("Could not find total pages for domain");
         goto error_out;
-    }
-
-    if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL )
-        goto error_out;
-
-    if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
-    {
-        if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 )
-        {
-            PERROR("Could not open the initial ramdisk image");
-            goto error_out;
-        }
-
-        initrd_size = xc_get_filesz(initrd_fd);
-
-        if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL )
-        {
-            PERROR("Could not allocate decompression state for initrd");
-            goto error_out;
-        }
     }
 
 #ifdef VALGRIND
@@ -935,7 +917,8 @@ int xc_linux_build(int xc_handle,
     memset(ctxt, 0, sizeof(*ctxt));
 
     if ( setup_guest(xc_handle, domid, image, image_size, 
-                     initrd_gfd, initrd_size, nr_pages, 
+                     initrd, initrd_len,
+                     nr_pages, 
                      &vstartinfo_start, &vkern_entry,
                      &vstack_start, ctxt, cmdline,
                      op.u.getdomaininfo.shared_info_frame,
@@ -945,12 +928,6 @@ int xc_linux_build(int xc_handle,
         ERROR("Error constructing guest OS");
         goto error_out;
     }
-
-    if ( initrd_fd >= 0 )
-        close(initrd_fd);
-    if ( initrd_gfd )
-        gzclose(initrd_gfd);
-    free(image);
 
 #ifdef __ia64__
     /* based on new_thread in xen/arch/ia64/domain.c */
@@ -1037,12 +1014,149 @@ int xc_linux_build(int xc_handle,
     return rc;
 
  error_out:
-    if ( initrd_gfd != NULL )
-        gzclose(initrd_gfd);
-    else if ( initrd_fd >= 0 )
-        close(initrd_fd);
+    return -1;
+}
+
+/* xc_linux_build_mem
+ *
+ * Create a domain for a para-virtualized Linux, using buffers containing the 
kernel
+ * and, possibly, the ramdisk.  This allows for use in situations where files 
may
+ * not be readily available.
+ *
+ */
+
+int xc_linux_build_mem(int xc_handle,
+                       uint32_t domid,
+                       unsigned char *image_buffer,
+                       unsigned long image_size,
+                       unsigned char *initrd,
+                       unsigned long initrd_len,
+                       const char *cmdline,
+                       unsigned long flags,
+                       unsigned int store_evtchn,
+                       unsigned long *store_mfn,
+                       unsigned int console_evtchn,
+                       unsigned long *console_mfn)
+{
+    int                 sts;
+    unsigned char       *img_buf;
+    unsigned long       img_len;
+    unsigned char       *ram_buf;
+    unsigned long       ram_len;
+
+    /* A kernel buffer is required */
+
+    if ( (image_buffer == NULL) || (image_size == 0) )
+    {
+        ERROR("kernel image buffer not present");
+        return EINVAL;
+    }
+
+    /* If it's gzipped, inflate it;  otherwise, use as is */
+    /*  xc_inflate_buffer may return the same buffer pointer if */
+    /* the buffer is already inflated */
+
+    img_buf = xc_inflate_buffer(image_buffer, image_size, &img_len);
+    if (img_buf == NULL)
+    {
+        ERROR("unable to inflate kernel image buffer");
+       return EFAULT;
+    }
+
+    /* RAM disks are optional; if we get one, inflate it */
+
+    if (initrd != NULL)
+    {
+        ram_buf = xc_inflate_buffer(initrd, initrd_len, &ram_len);
+        if (ram_buf == NULL)
+        {
+            ERROR("unable to inflate ram disk buffer");
+            sts = -1;
+            goto out;
+        }
+    }
+    else
+    {
+        ram_buf = initrd;
+        ram_len = initrd_len;
+    }
+
+    sts = xc_linux_build_internal(xc_handle, domid, img_buf, img_len,
+                                  ram_buf, ram_len, cmdline, flags,
+                                  store_evtchn, store_mfn,
+                                  console_evtchn, console_mfn);
+
+ out:
+    /* The inflation routines may pass back the same buffer so be */
+    /* sure that we have a buffer and that it's not the one passed in. */
+    /* Don't unnecessarily annoy/surprise/confound the caller */
+
+    if ( (img_buf != NULL) && (img_buf != image_buffer) )
+        free(img_buf);
+    if ( (ram_buf != NULL) && (ram_buf != initrd) )
+        free(ram_buf);
+
+    return sts;
+}
+
+/* xc_linux_build
+ *
+ * Create a domain for a para-virtualized Linux, using files/filenames
+ *
+ */
+
+int xc_linux_build(int xc_handle,
+                   uint32_t domid,
+                   const char *image_name,
+                   const char *initrd_name,
+                   const char *cmdline,
+                   unsigned long flags,
+                   unsigned int store_evtchn,
+                   unsigned long *store_mfn,
+                   unsigned int console_evtchn,
+                   unsigned long *console_mfn)
+{
+    unsigned char *image;
+    long image_size;
+    unsigned char *ram;
+    unsigned long ram_size;
+    int  sts;
+
+    /* xc_linux_build_internal always takes uncompressed buffers of the */
+    /* kernel image and ram disk, so read the files here and create them */
+
+    /* Bring uncompressed kernel image into memory */
+
+    if ( (image_name == NULL) ||
+         ((image = (unsigned char *)xc_read_image(image_name, (unsigned long 
*)&image_size)) == NULL ))
+        return -1;
+
+    /* The ramdisk is optional */
+  
+    if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) )
+    {
+        ram = (unsigned char *)xc_read_image(initrd_name, &ram_size);
+        if (ram == NULL)
+        {
+            free(image);
+            return -1;
+        }
+    }
+    else
+    {
+        ram = NULL;
+        ram_size = 0;
+    }
+
+    sts = xc_linux_build_internal(xc_handle, domid, image, image_size,
+                                  ram, ram_size, cmdline, flags,
+                                  store_evtchn, store_mfn,
+                                  console_evtchn, console_mfn);
     free(image);
-    return -1;
+    if (ram != NULL)
+        free(ram);
+
+    return sts;
 }
 
 /*
diff -r 1d36cca98fc3 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Fri Feb 10 12:35:19 2006 +0100
+++ b/tools/libxc/xenguest.h    Mon Feb 13 17:10:05 2006 -0500
@@ -42,6 +42,22 @@ int xc_linux_restore(int xc_handle, int 
                      unsigned long *store_mfn, unsigned int console_evtchn,
                     unsigned long *console_mfn);
 
+/**
+ * This function will create a domain for a paravirtualized Linux
+ * using file names pointing to kernel and ramdisk
+ *
+ * @parm xc_handle a handle to an open hypervisor interface
+ * @parm domid the id of the domain
+ * @param image_name name of the kernel image file
+ * @param ramdisk_name name of the ramdisk image file
+ * @parm cmdline command line string
+ * @parm flags domain creation flags
+ * @parm store_evtchn the store event channel for this domain to use
+ * @parm store_mfn returned with the mfn of the store page
+ * @parm console_evtchn the console event channel for this domain to use
+ * @parm conole_mfn returned with the mfn of the console page
+ * @return 0 on success, -1 on failure
+ */
 int xc_linux_build(int xc_handle,
                    uint32_t domid,
                    const char *image_name,
@@ -52,6 +68,37 @@ int xc_linux_build(int xc_handle,
                    unsigned long *store_mfn,
                    unsigned int console_evtchn,
                    unsigned long *console_mfn);
+
+/**
+ * This function will create a domain for a paravirtualized Linux
+ * using buffers for kernel and initrd
+ *
+ * @param xc_handle a handle to an open hypervisor interface
+ * @param domid the id of the domain
+ * @param image_buffer buffer containing kernel image
+ * @param image_size size of the kernel image buffer
+ * @param initrd_buffer name of the ramdisk image file
+ * @param initrd_size size of the ramdisk buffer
+ * @param cmdline command line string
+ * @param flags domain creation flags
+ * @param store_evtchn the store event channel for this domain to use
+ * @param store_mfn returned with the mfn of the store page
+ * @param console_evtchn the console event channel for this domain to use
+ * @param conole_mfn returned with the mfn of the console page
+ * @return 0 on success, -1 on failure
+ */
+int xc_linux_build_mem(int xc_handle,
+                      uint32_t domid,
+                      unsigned char *image_buffer,
+                      unsigned long image_size,
+                      unsigned char *initrd_buffer,
+                      unsigned long initrd_size,
+                      const char *cmdline,
+                      unsigned long flags,
+                      unsigned int store_evtchn,
+                      unsigned long *store_mfn,
+                      unsigned int console_evtchn,
+                      unsigned long *console_mfn);
 
 int xc_hvm_build(int xc_handle,
                  uint32_t domid,
@@ -64,4 +111,16 @@ int xc_hvm_build(int xc_handle,
                  unsigned int store_evtchn,
                  unsigned long *store_mfn);
 
+int xc_hvm_build_mem(int xc_handle,
+                    uint32_t domid,
+                    int memsize,
+                    unsigned char *image_buffer,
+                    unsigned long image_size,
+                    unsigned int control_evtchn,
+                    unsigned int vcpus,
+                    unsigned int acpi,
+                    unsigned int apic,
+                    unsigned int store_evtchn,
+                    unsigned long *store_mfn);
+
 #endif // XENGUEST_H
diff -r 1d36cca98fc3 tools/libxc/xg_private.c
--- a/tools/libxc/xg_private.c  Fri Feb 10 12:35:19 2006 +0100
+++ b/tools/libxc/xg_private.c  Mon Feb 13 17:10:05 2006 -0500
@@ -10,15 +10,21 @@
 
 #include "xg_private.h"
 
-char *xc_read_kernel_image(const char *filename, unsigned long *size)
+char *xc_read_image(const char *filename, unsigned long *size)
 {
     int kernel_fd = -1;
     gzFile kernel_gfd = NULL;
     char *image = NULL;
     unsigned int bytes;
 
-    if ( filename == NULL )
-        goto out;
+
+    /* Check for non-null input.  We could handle a NULL size, but it's */
+    /* not clear what value it provides to not know the length on return, */
+    /* especially since it's unconditionally updated just below. */
+    /* Also, just return - we haven't done anything requiring cleanup */
+
+    if ( ( filename == NULL ) || (size == NULL) )
+        return NULL;
 
     if ( (kernel_fd = open(filename, O_RDONLY)) < 0 )
     {
@@ -60,6 +66,59 @@ char *xc_read_kernel_image(const char *f
     return image;
 }
 
+unsigned char *xc_inflate_buffer(unsigned char *in_buf, unsigned long in_size,
+                                 unsigned long *out_size)
+{
+    int                 sts;
+    z_stream            zStream;
+    unsigned long       out_len;
+    unsigned char       *out_buf;
+
+    if ( (in_buf[0] == 0x1F) && (in_buf[1] == 0x8B) )
+    {
+      out_len = in_buf[in_size-4] +
+               (256 * (in_buf[in_size-3] +
+                       (256 * (in_buf[in_size-2] +
+                               (256 * in_buf[in_size-1])))));
+      bzero(&zStream, sizeof(zStream));
+      out_buf = malloc(out_len + 16);        /* Leave a little extra space */
+      if (out_buf == NULL) {
+       ERROR("Error mallocing buffer\n");
+       return NULL;
+      }
+
+      zStream.next_in = in_buf;
+      zStream.avail_in = in_size;
+      zStream.next_out = out_buf;
+      zStream.avail_out = out_len+16;
+      sts = inflateInit2(&zStream, (MAX_WBITS+32));   /* +32 means "handle 
gzip" */
+      if (sts != Z_OK)
+      {
+       ERROR("inflateInit failed, sts %d\n", sts);
+       free(out_buf);
+       return NULL;
+      }
+
+      /* Inflate in one pass/call */
+
+      sts = inflate(&zStream, Z_FINISH);
+      if (sts != Z_STREAM_END)
+      {
+       ERROR("inflate failed, sts %d\n", sts);
+       free(out_buf);
+       return NULL;
+      }
+    } else {
+      out_buf = in_buf;
+      out_len = in_size;
+    }
+    
+    if (out_size != NULL)
+      *out_size = out_len;
+       
+    return out_buf;
+}
+
 /*******************/
 
 int pin_table(
@@ -83,6 +142,11 @@ unsigned long csum_page (void * page)
     unsigned long *p = page;
     unsigned long long sum=0;
 
+    // Return 0 checksum for NULL input
+
+    if (page == NULL)
+      return 0;
+
     for ( i = 0; i < (PAGE_SIZE/sizeof(unsigned long)); i++ )
         sum += p[i];
 
diff -r 1d36cca98fc3 tools/libxc/xg_private.h
--- a/tools/libxc/xg_private.h  Fri Feb 10 12:35:19 2006 +0100
+++ b/tools/libxc/xg_private.h  Mon Feb 13 17:10:05 2006 -0500
@@ -26,7 +26,11 @@
 #endif
 
 
-char *xc_read_kernel_image(const char *filename, unsigned long *size);
+char *xc_read_image(const char *filename, unsigned long *size);
+unsigned char *xc_inflate_buffer(unsigned char *in_buf,
+                                 unsigned long in_size,
+                                 unsigned long *out_size);
+
 unsigned long csum_page (void * page);
 
 #define _PAGE_PRESENT   0x001
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH][RESEND] - add parallel routines to support domain building via buffers, Ben Thomas <=