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 >[email protected]; \
+ if has_header bzlib.h; then \
+ echo "-DHAVE_BZLIB" >>[email protected]; \
+ echo "-lbz2" >>[email protected]; \
+ echo " - BZIP2 decompression supported"; \
+ fi; \
+ if has_header lzma.h; then \
+ echo "-DHAVE_LZMA" >>[email protected]; \
+ echo "-llzma" >>[email protected]; \
+ echo " - LZMA decompression supported"; \
+ fi; \
+ mv [email protected] $@)
+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 <[email protected]>.
* written 2007 by Jeremy Fitzhardinge <[email protected]>
* written 2008 by Ian Campbell <[email protected]>
+ * written 2009 by Chris Lalancette <[email protected]>
*
*/
#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
[email protected]
https://www.redhat.com/mailman/listinfo/fedora-xen