On Thu, Aug 20, 2009 at 10:04:09PM +0300, Pasi Kärkkäinen wrote: > 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.. > Here's updated patch that actually works. I added it to xen-3.4.1-1.src.rpm and verified the resulting rpms are able to boot lzma compressed kernels. It's still not final patch, since the stubdom/pvgrub bzip2/lzma support is not yet included in this patch (until the proper method for Makefile hacks is determined upstream). -- Pasi
--- xen-3.4-testing.hg/tools/libxc/Makefile 2009-08-23 16:00:35.000000000 +0300 +++ xen-unstable.hg/tools/libxc/Makefile 2009-08-23 19:22:12.000000000 +0300 @@ -84,7 +86,7 @@ all: build .PHONY: build -build: +build: .zlib.deps $(MAKE) libs .PHONY: libs @@ -112,7 +114,7 @@ .PHONY: clean clean: - rm -rf *.rpm $(LIB) *~ $(DEPS) \ + rm -rf *.rpm $(LIB) *~ $(DEPS) .*.deps \ $(CTRL_LIB_OBJS) $(CTRL_PIC_OBJS) \ $(GUEST_LIB_OBJS) $(GUEST_PIC_OBJS) @@ -149,6 +151,34 @@ libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR) ln -sf $< $@ +ifeq ($(CONFIG_MiniOS),y) +.zlib.deps: + echo >$@ +else +.zlib.deps: + @(set -e; \ + . ../check/funcs.sh; \ + echo >$@.new; \ + if has_header bzlib.h; then \ + echo "-DHAVE_BZLIB" >>$@.new; \ + echo "-lbz2" >>$@.new; \ + echo " - BZIP2 decompression supported"; \ + fi; \ + if has_header lzma.h; then \ + echo "-DHAVE_LZMA" >>$@.new; \ + echo "-llzma" >>$@.new; \ + echo " - LZMA decompression supported"; \ + fi; \ + mv $@.new $@) +endif + +xc_dom_bzimageloader.o: .zlib.deps +xc_dom_bzimageloader.o: CFLAGS += $(shell grep D .zlib.deps) + +xc_dom_bzimageloader.opic: .zlib.deps +xc_dom_bzimageloader.opic: CFLAGS += $(shell grep D .zlib.deps) + +libxenguest.so.$(MAJOR).$(MINOR): LDFLAGS += $(shell grep l .zlib.deps) 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) --- xen-3.4-testing.hg/tools/libxc/xc_dom_bzimageloader.c 2009-08-23 16:00:35.000000000 +0300 +++ xen-unstable.hg/tools/libxc/xc_dom_bzimageloader.c 2009-08-23 17:36:28.000000000 +0300 @@ -11,6 +11,7 @@ * 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> @@ -20,43 +21,291 @@ #include "xg_private.h" #include "xc_dom.h" +#if defined(HAVE_BZLIB) + +#include <bzlib.h> + +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; + + for ( ; ; ) + { + 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, (long unsigned int) total); + + *blob = out_buf; + *size = total; + + bzip2_cleanup: + BZ2_bzDecompressEnd(&stream); + + return retval; +} + +#else /* !defined(HAVE_BZLIB) */ + +static int xc_try_bzip2_decode( + struct xc_dom_image *dom, void **blob, size_t *size) +{ + xc_dom_printf("%s: BZIP2 decompress support unavailable\n", + __FUNCTION__); + return -1; +} + +#endif + +#if defined(HAVE_LZMA) + +#include <lzma.h> + +static 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_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; + + xc_dom_printf("\nbeginning of xc_try_lzma_decode\n"); + + 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; + + for ( ; ; ) + { + 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, (size_t)stream.total_out); + + *blob = out_buf; + *size = stream.total_out; + + lzma_cleanup: + lzma_end(&stream); + + return retval; +} + +#else /* !defined(HAVE_LZMA) */ + +static int xc_try_lzma_decode( + struct xc_dom_image *dom, void **blob, size_t *size) +{ + xc_dom_printf("%s: LZMA decompress support unavailable\n", + __FUNCTION__); + return -1; +} + +#endif + struct setup_header { - uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */ - uint8_t setup_sects; - uint16_t root_flags; - uint32_t syssize; - uint16_t ram_size; - uint16_t vid_mode; - uint16_t root_dev; - uint16_t boot_flag; - uint16_t jump; - uint32_t header; -#define HDR_MAGIC "HdrS" -#define HDR_MAGIC_SZ 4 - uint16_t version; -#define VERSION(h,l) (((h)<<8) | (l)) - uint32_t realmode_swtch; - uint16_t start_sys; - uint16_t kernel_version; - uint8_t type_of_loader; - uint8_t loadflags; - uint16_t setup_move_size; - uint32_t code32_start; - uint32_t ramdisk_image; - uint32_t ramdisk_size; - uint32_t bootsect_kludge; - uint16_t heap_end_ptr; - uint16_t _pad1; - uint32_t cmd_line_ptr; - uint32_t initrd_addr_max; - uint32_t kernel_alignment; - uint8_t relocatable_kernel; - uint8_t _pad2[3]; - uint32_t cmdline_size; - uint32_t hardware_subarch; - uint64_t hardware_subarch_data; - uint32_t payload_offset; - uint32_t payload_length; + uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */ + uint8_t setup_sects; + uint16_t root_flags; + uint32_t syssize; + uint16_t ram_size; + uint16_t vid_mode; + uint16_t root_dev; + uint16_t boot_flag; + uint16_t jump; + uint32_t header; +#define HDR_MAGIC "HdrS" +#define HDR_MAGIC_SZ 4 + uint16_t version; +#define VERSION(h,l) (((h)<<8) | (l)) + uint32_t realmode_swtch; + uint16_t start_sys; + uint16_t kernel_version; + uint8_t type_of_loader; + uint8_t loadflags; + uint16_t setup_move_size; + uint32_t code32_start; + uint32_t ramdisk_image; + uint32_t ramdisk_size; + uint32_t bootsect_kludge; + uint16_t heap_end_ptr; + uint16_t _pad1; + uint32_t cmd_line_ptr; + uint32_t initrd_addr_max; + uint32_t kernel_alignment; + uint8_t relocatable_kernel; + uint8_t _pad2[3]; + uint32_t cmdline_size; + uint32_t hardware_subarch; + uint64_t hardware_subarch_data; + uint32_t payload_offset; + uint32_t payload_length; } __attribute__((packed)); extern struct xc_dom_loader elf_loader; @@ -70,22 +319,28 @@ 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; + + xc_dom_printf("\nxc_dom_probe_bzimage_kernel\n"); + +#if defined(HAVE_LZMA) + xc_dom_printf("\nEXTRA DEBUG: HAVE_LZMA defined\n"); +#endif 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 +348,68 @@ 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 ) + xc_dom_printf("\nbefore first memcmp\n"); + if ( memcmp(dom->kernel_blob, "\037\213", 2) == 0 ) + { + xc_dom_printf("\nbefore xc_dom_try_gunzip\n"); + 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 ) { - if ( verbose ) - xc_dom_panic(XC_INVALID_KERNEL, "%s: unable to decompress kernel\n", + xc_dom_printf("\nbefore xc_try_bzip2_decode\n"); + 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 ) + { + xc_dom_printf("\nbefore xc_try_lzma_decode\n"); + 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); @@ -145,6 +429,7 @@ static void __init register_loader(void) { + xc_dom_printf("\n__init bzImage loader\n"); xc_dom_register_loader(&bzimage_loader); }
-- Fedora-xen mailing list Fedora-xen@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/fedora-xen