From 5e73e3548ce70e433a03843ac4fc21a49277baad Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 15 Mar 2013 18:09:51 +0000 Subject: Add DomU xz kernel decompression Signed-off-by: Jan Beulich xen-unstable changeset: 4afea3d65321c40bb8afec833c860f92176bfb42 xen-unstable date: Wed Mar 9 16:19:36 2011 +0000 Signed-off-by: Ian Jackson [ This is byte-for-byte identical to Bastian Blank's backport of the same changeset to xen-4.1, as found in Debian xen_4.1.4-2.* patch debian/patches/upstream-23002:eb64b8f8eebb -iwj ] --- tools/libxc/xc_dom_bzimageloader.c | 90 +++++++++++++++++++++++++++----------- 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/tools/libxc/xc_dom_bzimageloader.c b/tools/libxc/xc_dom_bzimageloader.c index 73cfad11eb..c5737db0d5 100644 --- a/tools/libxc/xc_dom_bzimageloader.c +++ b/tools/libxc/xc_dom_bzimageloader.c @@ -187,11 +187,10 @@ static int xc_try_bzip2_decode( #include -static int xc_try_lzma_decode( - struct xc_dom_image *dom, void **blob, size_t *size) +static int _xc_try_lzma_decode( + struct xc_dom_image *dom, void **blob, size_t *size, + lzma_stream *stream, lzma_ret ret, const char *what) { - lzma_stream stream = LZMA_STREAM_INIT; - lzma_ret ret; lzma_action action = LZMA_RUN; unsigned char *out_buf; unsigned char *tmp_buf; @@ -201,14 +200,13 @@ static int xc_try_lzma_decode( if ( dom->kernel_size == 0) { - DOMPRINTF("LZMA: Input is 0 size"); + DOMPRINTF("%s: Input is 0 size", what); return -1; } - ret = lzma_alone_decoder(&stream, 128*1024*1024); if ( ret != LZMA_OK ) { - DOMPRINTF("LZMA: Failed to init stream decoder"); + DOMPRINTF("%s: Failed to init decoder", what); return -1; } @@ -220,22 +218,22 @@ static int xc_try_lzma_decode( out_buf = malloc(outsize); if ( out_buf == NULL ) { - DOMPRINTF("LZMA: Failed to alloc memory"); + DOMPRINTF("%s: Failed to alloc memory", what); goto lzma_cleanup; } - stream.next_in = dom->kernel_blob; - stream.avail_in = dom->kernel_size; + stream->next_in = dom->kernel_blob; + stream->avail_in = dom->kernel_size; - stream.next_out = out_buf; - stream.avail_out = dom->kernel_size; + stream->next_out = out_buf; + stream->avail_out = dom->kernel_size; for ( ; ; ) { - ret = lzma_code(&stream, action); + ret = lzma_code(stream, action); if ( ret == LZMA_STREAM_END ) { - DOMPRINTF("LZMA: Saw data stream end"); + DOMPRINTF("%s: Saw data stream end", what); retval = 0; break; } @@ -272,25 +270,25 @@ static int xc_try_lzma_decode( msg = "Internal program error (bug)"; break; } - DOMPRINTF("%s: LZMA decompression error %s", - __FUNCTION__, msg); + DOMPRINTF("%s: %s decompression error %s", + __FUNCTION__, what, msg); free(out_buf); goto lzma_cleanup; } - if ( stream.avail_out == 0 ) + if ( stream->avail_out == 0 ) { /* Protect against output buffer overflow */ if ( outsize > SIZE_MAX / 2 ) { - DOMPRINTF("LZMA: output buffer overflow"); + DOMPRINTF("%s: output buffer overflow", what); free(out_buf); goto lzma_cleanup; } if ( xc_dom_kernel_check_size(dom, outsize * 2) ) { - DOMPRINTF("LZMA: output too large"); + DOMPRINTF("%s: output too large", what); free(out_buf); goto lzma_cleanup; } @@ -298,32 +296,61 @@ static int xc_try_lzma_decode( tmp_buf = realloc(out_buf, outsize * 2); if ( tmp_buf == NULL ) { - DOMPRINTF("LZMA: Failed to realloc memory"); + DOMPRINTF("%s: Failed to realloc memory", what); free(out_buf); goto lzma_cleanup; } out_buf = tmp_buf; - stream.next_out = out_buf + outsize; - stream.avail_out = (outsize * 2) - outsize; + stream->next_out = out_buf + outsize; + stream->avail_out = (outsize * 2) - outsize; outsize *= 2; } } - DOMPRINTF("%s: LZMA decompress OK, 0x%zx -> 0x%zx", - __FUNCTION__, *size, (size_t)stream.total_out); + DOMPRINTF("%s: %s decompress OK, 0x%zx -> 0x%zx", + __FUNCTION__, what, *size, (size_t)stream->total_out); *blob = out_buf; - *size = stream.total_out; + *size = stream->total_out; lzma_cleanup: - lzma_end(&stream); + lzma_end(stream); return retval; } +/* 128 Mb is the minimum size (half-way) documented to work for all inputs. */ +#define LZMA_BLOCK_SIZE (128*1024*1024) + +static int xc_try_xz_decode( + struct xc_dom_image *dom, void **blob, size_t *size) +{ + lzma_stream stream = LZMA_STREAM_INIT; + lzma_ret ret = lzma_stream_decoder(&stream, LZMA_BLOCK_SIZE, 0); + + return _xc_try_lzma_decode(dom, blob, size, &stream, ret, "XZ"); +} + +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_alone_decoder(&stream, LZMA_BLOCK_SIZE); + + return _xc_try_lzma_decode(dom, blob, size, &stream, ret, "LZMA"); +} + #else /* !defined(HAVE_LZMA) */ +static int xc_try_xz_decode( + struct xc_dom_image *dom, void **blob, size_t *size) +{ + DOMPRINTF("%s: XZ decompress support unavailable", + __FUNCTION__); + return -1; +} + static int xc_try_lzma_decode( struct xc_dom_image *dom, void **blob, size_t *size) { @@ -659,6 +686,17 @@ static int xc_dom_probe_bzimage_kernel(struct xc_dom_image *dom) return -EINVAL; } } + else if ( check_magic(dom, "\3757zXZ", 6) ) + { + ret = xc_try_xz_decode(dom, &dom->kernel_blob, &dom->kernel_size); + if ( ret < 0 ) + { + xc_dom_panic(dom->xch, XC_INVALID_KERNEL, + "%s unable to XZ decompress kernel", + __FUNCTION__); + return -EINVAL; + } + } else if ( check_magic(dom, "\135\000", 2) ) { ret = xc_try_lzma_decode(dom, &dom->kernel_blob, &dom->kernel_size); -- cgit v1.2.3