[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Allow LZO compressed bzImage to be used as DomU kernel
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1276604411 -3600 # Node ID 98c118970b4db0f03a7b54c41d098ce518ad9560 # Parent d8333666361d5d5e62f6813e72425c3888f006d7 Allow LZO compressed bzImage to be used as DomU kernel ... since recently Linux added this as another kernel compression method. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx> --- tools/libxc/Makefile | 4 tools/libxc/xc_dom_bzimageloader.c | 193 +++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) diff -r d8333666361d -r 98c118970b4d tools/libxc/Makefile --- a/tools/libxc/Makefile Tue Jun 15 13:19:33 2010 +0100 +++ b/tools/libxc/Makefile Tue Jun 15 13:20:11 2010 +0100 @@ -169,6 +169,10 @@ zlib-options = $(shell \ if has_header lzma.h; then \ echo "-DHAVE_LZMA"; \ echo "-llzma"; \ + fi; \ + if has_header lzo/lzo1x.h; then \ + echo "-DHAVE_LZO1X"; \ + echo "-llzo2"; \ fi) | grep $(1)) endif diff -r d8333666361d -r 98c118970b4d tools/libxc/xc_dom_bzimageloader.c --- a/tools/libxc/xc_dom_bzimageloader.c Tue Jun 15 13:19:33 2010 +0100 +++ b/tools/libxc/xc_dom_bzimageloader.c Tue Jun 15 13:20:11 2010 +0100 @@ -268,6 +268,188 @@ static int xc_try_lzma_decode( { DOMPRINTF("%s: LZMA decompress support unavailable", __FUNCTION__); + return -1; +} + +#endif + +#if defined(HAVE_LZO1X) + +#include <lzo/lzo1x.h> + +#define LZOP_HEADER_HAS_FILTER 0x00000800 +#define LZOP_MAX_BLOCK_SIZE (64*1024*1024) + +static inline uint_fast16_t lzo_read_16(const unsigned char *buf) +{ + return buf[1] | (buf[0] << 8); +} + +static inline uint_fast32_t lzo_read_32(const unsigned char *buf) +{ + return lzo_read_16(buf + 2) | ((uint32_t)lzo_read_16(buf) << 16); +} + +static int xc_try_lzo1x_decode( + struct xc_dom_image *dom, void **blob, size_t *size) +{ + int ret; + const unsigned char *cur = dom->kernel_blob; + unsigned char *out_buf = NULL; + size_t left = dom->kernel_size; + const char *msg; + unsigned version; + static const unsigned char magic[] = { + 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a + }; + + ret = lzo_init(); + if ( ret != LZO_E_OK ) + { + DOMPRINTF("LZO1x: Failed to init library (%d)\n", ret); + return -1; + } + + if ( left < 16 || memcmp(cur, magic, 9) ) + { + DOMPRINTF("LZO1x: Unrecognized magic\n"); + return -1; + } + + /* get version (2bytes), skip library version (2), + * 'need to be extracted' version (2) and method (1) */ + version = lzo_read_16(cur + 9); + cur += 16; + left -= 16; + + if ( version >= 0x0940 ) + { + /* skip level */ + ++cur; + if ( left ) + --left; + } + + if ( left >= 4 && (lzo_read_32(cur) & LZOP_HEADER_HAS_FILTER) ) + ret = 8; /* flags + filter info */ + else + ret = 4; /* flags */ + + /* skip mode and mtime_low */ + ret += 8; + if ( version >= 0x0940 ) + ret += 4; /* skip mtime_high */ + + /* don't care about the file name, and skip checksum */ + if ( left > ret ) + ret += 1 + cur[ret] + 4; + + if ( left < ret ) + { + DOMPRINTF("LZO1x: Incomplete header\n"); + return -1; + } + cur += ret; + left -= ret; + + for ( *size = 0; ; ) + { + lzo_uint src_len, dst_len, out_len; + unsigned char *tmp_buf; + + msg = "Short input"; + if ( left < 4 ) + break; + + dst_len = lzo_read_32(cur); + if ( !dst_len ) + return 0; + + if ( dst_len > LZOP_MAX_BLOCK_SIZE ) + { + msg = "Block size too large"; + break; + } + + if ( left < 12 ) + break; + + src_len = lzo_read_32(cur + 4); + cur += 12; /* also skip block checksum info */ + left -= 12; + + msg = "Bad source length"; + if ( src_len <= 0 || src_len > dst_len || src_len > left ) + break; + + msg = "Failed to (re)alloc memory"; + tmp_buf = realloc(out_buf, *size + dst_len); + if ( tmp_buf == NULL ) + break; + + out_buf = tmp_buf; + out_len = dst_len; + + ret = lzo1x_decompress_safe(cur, src_len, + out_buf + *size, &out_len, NULL); + switch ( ret ) + { + case LZO_E_OK: + msg = "Input underrun"; + if ( out_len != dst_len ) + break; + + *blob = out_buf; + *size += out_len; + cur += src_len; + left -= src_len; + continue; + + case LZO_E_INPUT_NOT_CONSUMED: + msg = "Unconsumed input"; + break; + + case LZO_E_OUTPUT_OVERRUN: + msg = "Output overrun"; + break; + + case LZO_E_INPUT_OVERRUN: + msg = "Input overrun"; + break; + + case LZO_E_LOOKBEHIND_OVERRUN: + msg = "Look-behind overrun"; + break; + + case LZO_E_EOF_NOT_FOUND: + msg = "No EOF marker"; + break; + + case LZO_E_ERROR: + msg = "General error"; + break; + + default: + msg = "Internal program error (bug)"; + break; + } + + break; + } + + free(out_buf); + DOMPRINTF("LZO1x decompression error: %s\n", msg); + + return -1; +} + +#else /* !defined(HAVE_LZO1X) */ + +static int xc_try_lzo1x_decode( + struct xc_dom_image *dom, void **blob, size_t *size) +{ + DOMPRINTF("%s: LZO1x decompress support unavailable\n", + __FUNCTION__); return -1; } @@ -393,6 +575,17 @@ static int xc_dom_probe_bzimage_kernel(s return -EINVAL; } } + else if ( memcmp(dom->kernel_blob, "\x89LZO", 5) == 0 ) + { + ret = xc_try_lzo1x_decode(dom, &dom->kernel_blob, &dom->kernel_size); + if ( ret < 0 ) + { + xc_dom_panic(dom->xch, XC_INVALID_KERNEL, + "%s unable to LZO decompress kernel\n", + __FUNCTION__); + return -EINVAL; + } + } else { xc_dom_panic(dom->xch, XC_INVALID_KERNEL, _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |