[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH]: Implement bzip2 and LZMA loaders / fixed patch for Xen 3.4.1
On Thu, Aug 13, 2009 at 09:47:27AM +0200, Chris Lalancette wrote: > All, > Recent upstream kernels can be compressed using either gzip, bzip2, or > LZMA. However, the PV kernel loader in Xen currently only understands gzip, > and > will fail on the other two types. The attached patch implements kernel > decompression for gzip, bzip2, and LZMA so that kernels compressed with any of > these methods can be launched. Note that the patch is still a little bit > rough, > but I thought I would post it to get feedback about what I'm doing wrong. > I developed this against the RHEL-5 version of the xen tools, but a quick > look through xen-unstable shows that this should apply pretty easily to the > current code. > Attached are two patches: - Patch by Chris modified to apply to Xen 3.4.1 (only a small Makefile change) - Patch by me to fix compilation with gcc 4.4.0. -- Pasi > Signed-off-by: Chris Lalancette <clalance@xxxxxxxxxx> > diff -urp xen-3.1.0-src/tools/libxc/Makefile > xen-3.1.0-src.working/tools/libxc/Makefile > --- xen-3.1.0-src/tools/libxc/Makefile 2009-08-13 03:03:55.000000000 > -0400 > +++ xen-3.1.0-src.working/tools/libxc/Makefile 2009-08-12 > 11:56:38.000000000 -0400 > @@ -161,7 +161,7 @@ libxenguest.so.$(MAJOR): libxenguest.so. > 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 -lpthread > + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) > -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz > -llzma -lbz2 -lxenctrl -lpthread > > -include $(DEPS) > > diff -urp xen-3.1.0-src/tools/libxc/xc_dom_bzimageloader.c > xen-3.1.0-src.working/tools/libxc/xc_dom_bzimageloader.c > --- xen-3.1.0-src/tools/libxc/xc_dom_bzimageloader.c 2009-08-13 > 03:03:55.000000000 -0400 > +++ xen-3.1.0-src.working/tools/libxc/xc_dom_bzimageloader.c 2009-08-13 > 03:06:19.000000000 -0400 > @@ -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 @@ static unsigned int payload_offset(struc > 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 @@ static int check_bzimage_kernel(struct x > > 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-devel mailing list > Xen-devel@xxxxxxxxxxxxxxxxxxx > http://lists.xensource.com/xen-devel Attachment:
xen-loader-bzip2-lzma-xen34-fixed.patch Attachment:
xen-loader-bzip2-lzma-xen34-fixed-compilefix-gcc440.patch _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |