diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-11-09 07:52:27 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-11-09 07:52:27 +0000 |
commit | ab77e81f6521e97ac2fe2218013d5871a893db0f (patch) | |
tree | b9a2ce5ef8aa85c01c304eeea6ae6c965dda2947 /xen/arch/x86/bzimage.c | |
parent | 14ec087884b13aa9de838ab11fd4e67e255d4ded (diff) | |
download | xen-ab77e81f6521e97ac2fe2218013d5871a893db0f.tar.gz xen-ab77e81f6521e97ac2fe2218013d5871a893db0f.tar.bz2 xen-ab77e81f6521e97ac2fe2218013d5871a893db0f.zip |
x86/dom0: support bzip2 and lzma compressed bzImage payloads
This matches functionality in the tools already supporting the same
for DomU-s.
Code taken from Linux 2.6.32-rc and adjusted as little as possible to
be usable in Xen.
The question is whether, particularly for non-Linux Dom0-s, plain ELF
images compressed by bzip2 or lzma should also be supported.
Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/arch/x86/bzimage.c')
-rw-r--r-- | xen/arch/x86/bzimage.c | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/xen/arch/x86/bzimage.c b/xen/arch/x86/bzimage.c index 6408d88613..2fa87e063a 100644 --- a/xen/arch/x86/bzimage.c +++ b/xen/arch/x86/bzimage.c @@ -4,6 +4,7 @@ #include <xen/mm.h> #include <xen/string.h> #include <xen/types.h> +#include <xen/decompress.h> #include <asm/bzimage.h> #define HEAPORDER 3 @@ -93,28 +94,38 @@ static __init void flush_window(void) outcnt = 0; } -static __init int gzip_length(char *image, unsigned long image_len) +static __init unsigned long output_length(char *image, unsigned long image_len) { return *(uint32_t *)&image[image_len - 4]; } -static __init int perform_gunzip(char *output, char **_image_start, unsigned long *image_len) +static __init int gzip_check(char *image, unsigned long image_len) { - char *image = *_image_start; - int rc; - unsigned char magic0 = (unsigned char)image[0]; - unsigned char magic1 = (unsigned char)image[1]; + unsigned char magic0, magic1; - if ( magic0 != 0x1f || ( (magic1 != 0x8b) && (magic1 != 0x9e) ) ) + if ( image_len < 2 ) return 0; + magic0 = (unsigned char)image[0]; + magic1 = (unsigned char)image[1]; + + return (magic0 == 0x1f) && ((magic1 == 0x8b) || (magic1 == 0x9e)); +} + +static __init int perform_gunzip(char *output, char *image, unsigned long image_len) +{ + int rc; + + if ( !gzip_check(image, image_len) ) + return 1; + window = (unsigned char *)output; free_mem_ptr = (unsigned long)alloc_xenheap_pages(HEAPORDER, 0); free_mem_end_ptr = free_mem_ptr + (PAGE_SIZE << HEAPORDER); inbuf = (unsigned char *)image; - insize = *image_len; + insize = image_len; inptr = 0; makecrc(); @@ -125,8 +136,6 @@ static __init int perform_gunzip(char *output, char **_image_start, unsigned lo } else { - *_image_start = (char *)window; - *image_len = gzip_length(image, *image_len); rc = 0; } @@ -203,9 +212,12 @@ int __init bzimage_headroom(char *image_start, unsigned long image_length) img = image_start + (hdr->setup_sects+1) * 512; img += hdr->payload_offset; - headroom = gzip_length(img, hdr->payload_length); - headroom += headroom >> 12; /* Add 8 bytes for every 32K input block */ - headroom += (32768 + 18); /* Add 32K + 18 bytes of extra headroom */ + headroom = output_length(img, hdr->payload_length); + if (gzip_check(img, hdr->payload_length)) { + headroom += headroom >> 12; /* Add 8 bytes for every 32K input block */ + headroom += (32768 + 18); /* Add 32K + 18 bytes of extra headroom */ + } else + headroom += hdr->payload_length; headroom = (headroom + 4095) & ~4095; return headroom; @@ -215,6 +227,7 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im { struct setup_header *hdr = (struct setup_header *)(*image_start); int err = bzimage_check(hdr, *image_len); + unsigned long output_len; if (err < 1) return err; @@ -224,11 +237,18 @@ int __init bzimage_parse(char *image_base, char **image_start, unsigned long *im *image_start += (hdr->setup_sects+1) * 512; *image_start += hdr->payload_offset; *image_len = hdr->payload_length; + output_len = output_length(*image_start, *image_len); - if ( (err = perform_gunzip(image_base, image_start, image_len)) < 0 ) - return err; + if ( (err = perform_gunzip(image_base, *image_start, *image_len)) > 0 ) + err = decompress(*image_start, *image_len, image_base); + + if ( !err ) + { + *image_start = image_base; + *image_len = output_len; + } - return 0; + return err > 0 ? 0 : err; } /* |