Re: BZIP2 and LZMA support patch for Xen PV domU bootloader

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Aug 20, 2009 at 07:02:12PM +0100, Mark McLoughlin wrote:
> On Thu, 2009-08-20 at 19:44 +0300, Pasi Kärkkäinen wrote:
> > On Thu, Aug 20, 2009 at 05:05:17PM +0100, Mark McLoughlin wrote:
> > > On Thu, 2009-08-20 at 18:41 +0300, Pasi Kärkkäinen wrote:
> > > 
> > > > # CONFIG_KERNEL_GZIP is not set
> > > > # CONFIG_KERNEL_BZIP2 is not set
> > > > CONFIG_KERNEL_LZMA=y
> > > > 
> > > > OK, so the problem is the rawhide kernel is LZMA compressed. Wasn't this
> > > > changed back to GZIP earlier? 
> > > 
> > > Thanks for pointing that out, see:
> > > 
> > >   https://bugzilla.redhat.com/show_bug.cgi?id=515831
> > > 
> > > It got disabled on a branch for the F12 Alpha release, but never got
> > > disabled on the devel/ branch. Should be fixed now.
> > > 
> > 
> > Thanks. Now I'll just wait for the next kernel build.. :)
> > 
> > (or try applying the patch Chris sent to support BZIP2 and LZMA for Xen PV bootloader).
> 
> Testing Chris's patch would certainly be a good idea. LZMA will come
> back again in Fedora 13, so we should make sure to have the patch in
> good shape by then
> 

I actually already 'ported' the patch to Xen 3.4.1 and made sure it
compiles OK. I've included it (and extra gcc 4.4.0 compilefix) to this
email, and also sent them to xen-devel.

atm I'm trying to make the patch work/apply with Fedora xen-3.4.1-1 src.rpm ..
and sorting out some fedora/rpm specific compilation failure..

-- Pasi
--- xen-3.4-testing.hg/tools/libxc/Makefile.orig	2009-08-20 20:02:53.000000000 +0300
+++ xen-3.4-testing.hg/tools/libxc/Makefile	2009-08-20 19:57:00.000000000 +0300
@@ -150,7 +150,7 @@
 	ln -sf $< $@
 
 libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so
-	$(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl $(PTHREAD_LIBS)
+	$(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -llzma -lbz2 -lxenctrl $(PTHREAD_LIBS)
 
 -include $(DEPS)
 
--- xen-3.4-testing.hg/tools/libxc/xc_dom_bzimageloader.c.orig	2009-08-20 20:02:53.000000000 +0300
+++ xen-3.4-testing.hg/tools/libxc/xc_dom_bzimageloader.c	2009-08-20 20:05:44.000000000 +0300
@@ -11,15 +11,208 @@
  * written 2006 by Gerd Hoffmann <kraxel@xxxxxxx>.
  * written 2007 by Jeremy Fitzhardinge <jeremy@xxxxxxxxxxxxx>
  * written 2008 by Ian Campbell <ijc@xxxxxxxxxxxxxx>
+ * written 2009 by Chris Lalancette <clalance@xxxxxxxxxx>
  *
  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <inttypes.h>
+#include <bzlib.h>
+#include <lzma.h>
 
 #include "xg_private.h"
 #include "xc_dom.h"
 
+static inline uint64_t physmem(void)
+{
+	uint64_t ret = 0;
+
+	const long pagesize = sysconf(_SC_PAGESIZE);
+	const long pages = sysconf(_SC_PHYS_PAGES);
+	if (pagesize != -1 || pages != -1)
+		// According to docs, pagesize * pages can overflow.
+		// Simple case is 32-bit box with 4 GiB or more RAM,
+		// which may report exactly 4 GiB of RAM, and "long"
+		// being 32-bit will overflow. Casting to uint64_t
+		// hopefully avoids overflows in the near future.
+		ret = (uint64_t)(pagesize) * (uint64_t)(pages);
+
+    return ret;
+}
+
+static int xc_try_bzip2_decode(struct xc_dom_image *dom, void **blob, size_t *size)
+{
+    bz_stream stream;
+    int ret;
+    char *out_buf;
+    int retval = -1;
+    int outsize;
+    uint64_t total;
+
+    stream.bzalloc = NULL;
+    stream.bzfree = NULL;
+    stream.opaque = NULL;
+
+    ret = BZ2_bzDecompressInit(&stream, 0, 0);
+    if (ret != BZ_OK) {
+        xc_dom_printf("Error initting bz2 stream\n");
+        return -1;
+    }
+
+    /* sigh.  We don't know up-front how much memory we are going to need
+     * for the output buffer.  Allocate the output buffer to be equal
+     * the input buffer to start, and we'll realloc as needed.
+     */
+    outsize = dom->kernel_size;
+    out_buf = malloc(outsize);
+    if (out_buf == NULL) {
+        xc_dom_printf("Failed to alloc memory\n");
+        goto bzip2_cleanup;
+    }
+
+    stream.next_in = dom->kernel_blob;
+    stream.avail_in = dom->kernel_size;
+
+    stream.next_out = out_buf;
+    stream.avail_out = dom->kernel_size;
+
+    while (1) {
+        ret = BZ2_bzDecompress(&stream);
+        if (stream.avail_out == 0 || ret != BZ_OK) {
+            out_buf = realloc(out_buf, outsize * 2);
+            if (out_buf == NULL) {
+                xc_dom_printf("Failed to realloc memory\n");
+                break;
+            }
+
+            stream.next_out = out_buf + outsize;
+            stream.avail_out = (outsize * 2) - outsize;
+            outsize *= 2;
+        }
+
+        if (ret != BZ_OK) {
+            if (ret == BZ_STREAM_END) {
+                xc_dom_printf("Saw data stream end\n");
+                retval = 0;
+                break;
+            }
+            xc_dom_printf("BZIP error\n");
+        }
+    }
+
+    total = (stream.total_out_hi32 << 31) | stream.total_out_lo32;
+
+    xc_dom_printf("%s: BZIP2 decompress OK, 0x%zx -> 0x%lx\n", __FUNCTION__, *size, total);
+
+    *blob = out_buf;
+    *size = total;
+
+bzip2_cleanup:
+    BZ2_bzDecompressEnd(&stream);
+
+    return retval;
+}
+
+static int xc_try_lzma_decode(struct xc_dom_image *dom, void **blob, size_t *size)
+{
+    lzma_stream stream = LZMA_STREAM_INIT;
+    lzma_ret ret;
+    lzma_action action = LZMA_RUN;
+    unsigned char *out_buf;
+    int retval = -1;
+    int outsize;
+    const char *msg;
+
+    ret = lzma_alone_decoder(&stream, physmem() / 3);
+    if (ret != LZMA_OK) {
+        xc_dom_printf("Failed to init lzma stream decoder\n");
+        return -1;
+    }
+
+    /* sigh.  We don't know up-front how much memory we are going to need
+     * for the output buffer.  Allocate the output buffer to be equal
+     * the input buffer to start, and we'll realloc as needed.
+     */
+    outsize = dom->kernel_size;
+    out_buf = malloc(outsize);
+    if (out_buf == NULL) {
+        xc_dom_printf("Failed to alloc memory\n");
+        goto lzma_cleanup;
+    }
+
+    stream.next_in = dom->kernel_blob;
+    stream.avail_in = dom->kernel_size;
+
+    stream.next_out = out_buf;
+    stream.avail_out = dom->kernel_size;
+
+    while (1) {
+        ret = lzma_code(&stream, action);
+        if (stream.avail_out == 0 || ret != LZMA_OK) {
+            out_buf = realloc(out_buf, outsize * 2);
+            if (out_buf == NULL) {
+                xc_dom_printf("Failed to realloc memory\n");
+                break;
+            }
+
+            stream.next_out = out_buf + outsize;
+            stream.avail_out = (outsize * 2) - outsize;
+            outsize *= 2;
+        }
+
+        if (ret != LZMA_OK) {
+            if (ret == LZMA_STREAM_END) {
+                xc_dom_printf("Saw data stream end\n");
+                retval = 0;
+                break;
+            }
+
+            switch (ret) {
+            case LZMA_MEM_ERROR:
+                msg = strerror(ENOMEM);
+                break;
+
+            case LZMA_MEMLIMIT_ERROR:
+                msg = "Memory usage limit reached";
+                break;
+
+            case LZMA_FORMAT_ERROR:
+                msg = "File format not recognized";
+                break;
+
+            case LZMA_OPTIONS_ERROR:
+                // FIXME: Better message?
+                msg = "Unsupported compression options";
+                break;
+
+            case LZMA_DATA_ERROR:
+                msg = "File is corrupt";
+                break;
+
+            case LZMA_BUF_ERROR:
+                msg = "Unexpected end of input";
+                break;
+
+            default:
+                msg = "Internal program error (bug)";
+                break;
+            }
+            xc_dom_printf("%s: LZMA decompression error %s\n", __FUNCTION__, msg);
+            break;
+        }
+    }
+
+    xc_dom_printf("%s: LZMA decompress OK, 0x%zx -> 0x%zx\n", __FUNCTION__, *size, stream.total_out);
+
+    *blob = out_buf;
+    *size = stream.total_out;
+
+ lzma_cleanup:
+    lzma_end(&stream);
+
+    return retval;
+}
+
 struct setup_header {
 	uint8_t		_pad0[0x1f1];		/* skip uninteresting stuff */
 	uint8_t		setup_sects;
@@ -70,22 +263,22 @@
     return off;
 }
 
-static int check_bzimage_kernel(struct xc_dom_image *dom, int verbose)
+static int xc_dom_probe_bzimage_kernel(struct xc_dom_image *dom)
 {
     struct setup_header *hdr;
+    int ret;
 
     if ( dom->kernel_blob == NULL )
     {
-        if ( verbose )
-            xc_dom_panic(XC_INTERNAL_ERROR, "%s: no kernel image loaded\n",
-                         __FUNCTION__);
+        xc_dom_panic(XC_INTERNAL_ERROR, "%s: no kernel image loaded\n",
+                     __FUNCTION__);
         return -EINVAL;
     }
+
     if ( dom->kernel_size < sizeof(struct setup_header) )
     {
-        if ( verbose )
-            xc_dom_panic(XC_INTERNAL_ERROR, "%s: kernel image too small\n",
-                         __FUNCTION__);
+        xc_dom_panic(XC_INTERNAL_ERROR, "%s: kernel image too small\n",
+                     __FUNCTION__);
         return -EINVAL;
     }
 
@@ -93,39 +286,54 @@
 
     if ( memcmp(&hdr->header, HDR_MAGIC, HDR_MAGIC_SZ) != 0 )
     {
-        if ( verbose )
-            xc_dom_panic(XC_INVALID_KERNEL, "%s: kernel is not a bzImage\n",
-                         __FUNCTION__);
+        xc_dom_panic(XC_INVALID_KERNEL, "%s: kernel is not a bzImage\n",
+                     __FUNCTION__);
         return -EINVAL;
     }
 
     if ( hdr->version < VERSION(2,8) )
     {
-        if ( verbose )
-            xc_dom_panic(XC_INVALID_KERNEL, "%s: boot protocol too old (%04x)\n",
-                         __FUNCTION__, hdr->version);
+        xc_dom_panic(XC_INVALID_KERNEL, "%s: boot protocol too old (%04x)\n",
+                     __FUNCTION__, hdr->version);
         return -EINVAL;
     }
 
     dom->kernel_blob = dom->kernel_blob + payload_offset(hdr);
     dom->kernel_size = hdr->payload_length;
 
-    if ( xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size) == -1 )
-    {
-        if ( verbose )
-            xc_dom_panic(XC_INVALID_KERNEL, "%s: unable to decompress kernel\n",
+    if (memcmp(dom->kernel_blob, "\037\213", 2) == 0) {
+        ret = xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size);
+        if (ret == -1) {
+            xc_dom_panic(XC_INVALID_KERNEL, "%s: unable to gzip decompress kernel\n",
+                         __FUNCTION__);
+            return -EINVAL;
+        }
+    }
+    else if (memcmp(dom->kernel_blob, "\102\132\150", 3) == 0) {
+        ret = xc_try_bzip2_decode(dom, &dom->kernel_blob, &dom->kernel_size);
+        if (ret < 0) {
+            xc_dom_panic(XC_INVALID_KERNEL, "%s unable to BZIP2 decompress kernel",
+                         __FUNCTION__);
+            return -EINVAL;
+        }
+    }
+    else if (memcmp(dom->kernel_blob, "\135\000", 2) == 0) {
+        ret = xc_try_lzma_decode(dom, &dom->kernel_blob, &dom->kernel_size);
+        if (ret < 0) {
+            xc_dom_panic(XC_INVALID_KERNEL, "%s unable to LZMA decompress kernel\n",
                          __FUNCTION__);
+            return -EINVAL;
+        }
+    }
+    else {
+        xc_dom_panic(XC_INVALID_KERNEL, "%s: unknown compression format\n",
+                     __FUNCTION__);
         return -EINVAL;
     }
 
     return elf_loader.probe(dom);
 }
 
-static int xc_dom_probe_bzimage_kernel(struct xc_dom_image *dom)
-{
-    return check_bzimage_kernel(dom, 0);
-}
-
 static int xc_dom_parse_bzimage_kernel(struct xc_dom_image *dom)
 {
     return elf_loader.parser(dom);
--- xen-3.4-testing.hg/tools/libxc/xc_dom_bzimageloader.c.prev	2009-08-20 20:05:44.000000000 +0300
+++ xen-3.4-testing.hg/tools/libxc/xc_dom_bzimageloader.c	2009-08-20 21:05:11.000000000 +0300
@@ -102,7 +102,7 @@
 
     total = (stream.total_out_hi32 << 31) | stream.total_out_lo32;
 
-    xc_dom_printf("%s: BZIP2 decompress OK, 0x%zx -> 0x%lx\n", __FUNCTION__, *size, total);
+    xc_dom_printf("%s: BZIP2 decompress OK, 0x%zx -> 0x%lx\n", __FUNCTION__, *size, (long unsigned int) total);
 
     *blob = out_buf;
     *size = total;
@@ -202,7 +202,7 @@
         }
     }
 
-    xc_dom_printf("%s: LZMA decompress OK, 0x%zx -> 0x%zx\n", __FUNCTION__, *size, stream.total_out);
+    xc_dom_printf("%s: LZMA decompress OK, 0x%zx -> 0x%zx\n", __FUNCTION__, *size, (size_t) stream.total_out);
 
     *blob = out_buf;
     *size = stream.total_out;
--
Fedora-xen mailing list
Fedora-xen@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/fedora-xen

[Index of Archives]     [Fedora General]     [Fedora Music]     [Linux Kernel]     [Fedora Desktop]     [Fedora Directory]     [PAM]     [Big List of Linux Books]     [Gimp]     [Yosemite News]

  Powered by Linux