From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH] allow LZO compressed bzImage to be used as DomU kernel Date: Tue, 15 Jun 2010 12:54:54 +0100 Message-ID: <4C17862E0200007800006795@vpn.id2.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part476A111E.0__=" Return-path: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part476A111E.0__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline ... since recently Linux added this as another kernel compression method. Signed-off-by: Jan Beulich --- 2010-06-15.orig/tools/libxc/Makefile 2010-06-01 13:39:57.0000000= 00 +0200 +++ 2010-06-15/tools/libxc/Makefile 2010-06-15 09:50:59.000000000 = +0200 @@ -169,6 +169,10 @@ zlib-options =3D $(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 =20 --- 2010-06-15.orig/tools/libxc/xc_dom_bzimageloader.c 2010-06-01 = 13:39:57.000000000 +0200 +++ 2010-06-15/tools/libxc/xc_dom_bzimageloader.c 2010-06-15 = 09:52:32.000000000 +0200 @@ -273,6 +273,188 @@ static int xc_try_lzma_decode( =20 #endif =20 +#if defined(HAVE_LZO1X) + +#include + +#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 =3D dom->kernel_blob; + unsigned char *out_buf =3D NULL; + size_t left =3D dom->kernel_size; + const char *msg; + unsigned version; + static const unsigned char magic[] =3D { + 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a + }; + + ret =3D lzo_init(); + if ( ret !=3D 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 =3D lzo_read_16(cur + 9); + cur +=3D 16; + left -=3D 16; + + if ( version >=3D 0x0940 ) + { + /* skip level */ + ++cur; + if ( left ) + --left; + } + + if ( left >=3D 4 && (lzo_read_32(cur) & LZOP_HEADER_HAS_FILTER) ) + ret =3D 8; /* flags + filter info */ + else + ret =3D 4; /* flags */ + + /* skip mode and mtime_low */ + ret +=3D 8; + if ( version >=3D 0x0940 ) + ret +=3D 4; /* skip mtime_high */ + + /* don't care about the file name, and skip checksum */ + if ( left > ret ) + ret +=3D 1 + cur[ret] + 4; + + if ( left < ret ) + { + DOMPRINTF("LZO1x: Incomplete header\n"); + return -1; + } + cur +=3D ret; + left -=3D ret; + + for ( *size =3D 0; ; ) + { + lzo_uint src_len, dst_len, out_len; + unsigned char *tmp_buf; + + msg =3D "Short input"; + if ( left < 4 ) + break; + + dst_len =3D lzo_read_32(cur); + if ( !dst_len ) + return 0; + + if ( dst_len > LZOP_MAX_BLOCK_SIZE ) + { + msg =3D "Block size too large"; + break; + } + + if ( left < 12 ) + break; + + src_len =3D lzo_read_32(cur + 4); + cur +=3D 12; /* also skip block checksum info */ + left -=3D 12; + + msg =3D "Bad source length"; + if ( src_len <=3D 0 || src_len > dst_len || src_len > left ) + break; + + msg =3D "Failed to (re)alloc memory"; + tmp_buf =3D realloc(out_buf, *size + dst_len); + if ( tmp_buf =3D=3D NULL ) + break; + + out_buf =3D tmp_buf; + out_len =3D dst_len; + + ret =3D lzo1x_decompress_safe(cur, src_len, + out_buf + *size, &out_len, NULL); + switch ( ret ) + { + case LZO_E_OK: + msg =3D "Input underrun"; + if ( out_len !=3D dst_len ) + break; + + *blob =3D out_buf; + *size +=3D out_len; + cur +=3D src_len; + left -=3D src_len; + continue; + + case LZO_E_INPUT_NOT_CONSUMED: + msg =3D "Unconsumed input"; + break; + + case LZO_E_OUTPUT_OVERRUN: + msg =3D "Output overrun"; + break; + + case LZO_E_INPUT_OVERRUN: + msg =3D "Input overrun"; + break; + + case LZO_E_LOOKBEHIND_OVERRUN: + msg =3D "Look-behind overrun"; + break; + + case LZO_E_EOF_NOT_FOUND: + msg =3D "No EOF marker"; + break; + + case LZO_E_ERROR: + msg =3D "General error"; + break; + + default: + msg =3D "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; +} + +#endif + struct setup_header { uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */ uint8_t setup_sects; @@ -393,6 +575,17 @@ static int xc_dom_probe_bzimage_kernel(s return -EINVAL; } } + else if ( memcmp(dom->kernel_blob, "\x89LZO", 5) =3D=3D 0 ) + { + ret =3D xc_try_lzo1x_decode(dom, &dom->kernel_blob, &dom->kernel_s= ize); + 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, --=__Part476A111E.0__= Content-Type: text/plain; name="x86-lzo-domU.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-lzo-domU.patch" ... since recently Linux added this as another kernel compression=0Amethod.= =0A=0ASigned-off-by: Jan Beulich =0A=0A--- 2010-06-15.= orig/tools/libxc/Makefile 2010-06-01 13:39:57.000000000 +0200=0A+++ = 2010-06-15/tools/libxc/Makefile 2010-06-15 09:50:59.000000000 +0200=0A@@ = -169,6 +169,10 @@ zlib-options =3D $(shell = \=0A if has_header lzma.h; then \=0A echo = "-DHAVE_LZMA"; \=0A echo "-llzma"; = \=0A+ fi; = \=0A+ if has_header lzo/lzo1x.h; then \=0A+ echo = "-DHAVE_LZO1X"; \=0A+ echo "-llzo2"; = \=0A fi) | grep $(1))=0A endif=0A =0A--- 2010-06-15.ori= g/tools/libxc/xc_dom_bzimageloader.c 2010-06-01 13:39:57.000000000 = +0200=0A+++ 2010-06-15/tools/libxc/xc_dom_bzimageloader.c 2010-06-15 = 09:52:32.000000000 +0200=0A@@ -273,6 +273,188 @@ static int xc_try_lzma_dec= ode(=0A =0A #endif=0A =0A+#if defined(HAVE_LZO1X)=0A+=0A+#include = =0A+=0A+#define LZOP_HEADER_HAS_FILTER 0x00000800=0A+#define = LZOP_MAX_BLOCK_SIZE (64*1024*1024)=0A+=0A+static inline uint_fast16_t = lzo_read_16(const unsigned char *buf)=0A+{=0A+ return buf[1] | (buf[0] = << 8);=0A+}=0A+=0A+static inline uint_fast32_t lzo_read_32(const unsigned = char *buf)=0A+{=0A+ return lzo_read_16(buf + 2) | ((uint32_t)lzo_read_16= (buf) << 16);=0A+}=0A+=0A+static int xc_try_lzo1x_decode(=0A+ struct = xc_dom_image *dom, void **blob, size_t *size)=0A+{=0A+ int ret;=0A+ = const unsigned char *cur =3D dom->kernel_blob;=0A+ unsigned char = *out_buf =3D NULL;=0A+ size_t left =3D dom->kernel_size;=0A+ const = char *msg;=0A+ unsigned version;=0A+ static const unsigned char = magic[] =3D {=0A+ 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, = 0x0a=0A+ };=0A+=0A+ ret =3D lzo_init();=0A+ if ( ret !=3D = LZO_E_OK )=0A+ {=0A+ DOMPRINTF("LZO1x: Failed to init library = (%d)\n", ret);=0A+ return -1;=0A+ }=0A+=0A+ if ( left < 16 || = memcmp(cur, magic, 9) )=0A+ {=0A+ DOMPRINTF("LZO1x: Unrecognized = magic\n");=0A+ return -1;=0A+ }=0A+=0A+ /* get version = (2bytes), skip library version (2),=0A+ * 'need to be extracted' = version (2) and method (1) */=0A+ version =3D lzo_read_16(cur + 9);=0A+ = cur +=3D 16;=0A+ left -=3D 16;=0A+=0A+ if ( version >=3D 0x0940 = )=0A+ {=0A+ /* skip level */=0A+ ++cur;=0A+ if ( = left )=0A+ --left;=0A+ }=0A+=0A+ if ( left >=3D 4 && = (lzo_read_32(cur) & LZOP_HEADER_HAS_FILTER) )=0A+ ret =3D 8; /* = flags + filter info */=0A+ else=0A+ ret =3D 4; /* flags = */=0A+=0A+ /* skip mode and mtime_low */=0A+ ret +=3D 8;=0A+ if ( = version >=3D 0x0940 )=0A+ ret +=3D 4; /* skip mtime_high */=0A+=0A+ = /* don't care about the file name, and skip checksum */=0A+ if ( = left > ret )=0A+ ret +=3D 1 + cur[ret] + 4;=0A+=0A+ if ( left < = ret )=0A+ {=0A+ DOMPRINTF("LZO1x: Incomplete header\n");=0A+ = return -1;=0A+ }=0A+ cur +=3D ret;=0A+ left -=3D ret;=0A+=0A+ = for ( *size =3D 0; ; )=0A+ {=0A+ lzo_uint src_len, dst_len, = out_len;=0A+ unsigned char *tmp_buf;=0A+=0A+ msg =3D "Short = input";=0A+ if ( left < 4 )=0A+ break;=0A+=0A+ = dst_len =3D lzo_read_32(cur);=0A+ if ( !dst_len )=0A+ = return 0;=0A+=0A+ if ( dst_len > LZOP_MAX_BLOCK_SIZE )=0A+ = {=0A+ msg =3D "Block size too large";=0A+ break;=0A+ = }=0A+=0A+ if ( left < 12 )=0A+ break;=0A+=0A+ = src_len =3D lzo_read_32(cur + 4);=0A+ cur +=3D 12; /* also skip = block checksum info */=0A+ left -=3D 12;=0A+=0A+ msg =3D = "Bad source length";=0A+ if ( src_len <=3D 0 || src_len > dst_len = || src_len > left )=0A+ break;=0A+=0A+ msg =3D "Failed = to (re)alloc memory";=0A+ tmp_buf =3D realloc(out_buf, *size + = dst_len);=0A+ if ( tmp_buf =3D=3D NULL )=0A+ break;=0A+= =0A+ out_buf =3D tmp_buf;=0A+ out_len =3D dst_len;=0A+=0A+ = ret =3D lzo1x_decompress_safe(cur, src_len,=0A+ = out_buf + *size, &out_len, NULL);=0A+ switch ( ret = )=0A+ {=0A+ case LZO_E_OK:=0A+ msg =3D "Input = underrun";=0A+ if ( out_len !=3D dst_len )=0A+ = break;=0A+=0A+ *blob =3D out_buf;=0A+ *size +=3D = out_len;=0A+ cur +=3D src_len;=0A+ left -=3D = src_len;=0A+ continue;=0A+=0A+ case LZO_E_INPUT_NOT_CONSU= MED:=0A+ msg =3D "Unconsumed input";=0A+ break;=0A+= =0A+ case LZO_E_OUTPUT_OVERRUN:=0A+ msg =3D "Output = overrun";=0A+ break;=0A+=0A+ case LZO_E_INPUT_OVERRUN:=0A= + msg =3D "Input overrun";=0A+ break;=0A+=0A+ = case LZO_E_LOOKBEHIND_OVERRUN:=0A+ msg =3D "Look-behind = overrun";=0A+ break;=0A+=0A+ case LZO_E_EOF_NOT_FOUND:=0A= + msg =3D "No EOF marker";=0A+ break;=0A+=0A+ = case LZO_E_ERROR:=0A+ msg =3D "General error";=0A+ = break;=0A+=0A+ default:=0A+ msg =3D "Internal program = error (bug)";=0A+ break;=0A+ }=0A+=0A+ break;=0A+ = }=0A+=0A+ free(out_buf);=0A+ DOMPRINTF("LZO1x decompression = error: %s\n", msg);=0A+=0A+ return -1;=0A+}=0A+=0A+#else /* !defined(HAV= E_LZO1X) */=0A+=0A+static int xc_try_lzo1x_decode(=0A+ struct xc_dom_ima= ge *dom, void **blob, size_t *size)=0A+{=0A+ DOMPRINTF("%s: LZO1x = decompress support unavailable\n",=0A+ __FUNCTION__);=0A+ = return -1;=0A+}=0A+=0A+#endif=0A+=0A struct setup_header {=0A = uint8_t _pad0[0x1f1]; /* skip uninteresting stuff */=0A uint8_t = setup_sects;=0A@@ -393,6 +575,17 @@ static int xc_dom_probe_bzimage_kernel(= s=0A return -EINVAL;=0A }=0A }=0A+ else if ( = memcmp(dom->kernel_blob, "\x89LZO", 5) =3D=3D 0 )=0A+ {=0A+ ret = =3D xc_try_lzo1x_decode(dom, &dom->kernel_blob, &dom->kernel_size);=0A+ = if ( ret < 0 )=0A+ {=0A+ xc_dom_panic(dom->xch, = XC_INVALID_KERNEL,=0A+ "%s unable to LZO decompress= kernel\n",=0A+ __FUNCTION__);=0A+ = return -EINVAL;=0A+ }=0A+ }=0A else=0A {=0A = xc_dom_panic(dom->xch, XC_INVALID_KERNEL,=0A --=__Part476A111E.0__= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --=__Part476A111E.0__=--