diff options
author | Florian Fainelli <florian@openwrt.org> | 2009-11-19 00:17:22 +0100 |
---|---|---|
committer | Simon Horman <horms@verge.net.au> | 2009-11-30 16:06:14 +1100 |
commit | 4c2d9b93150d36d15bf75b050ed97cabd9a94774 (patch) | |
tree | 32d6b5e8180ebc0b88c3df1bdce8cf825e97e3bc /kexec/zlib.c | |
parent | d61381a70a57a01b87afee90c976675f047d447d (diff) |
add support for loading lzma compressed kernels
This patch allows one to load a lzma compressed kernel using kexec -l.
As I wanted the lzma code to be very similar to the existing
zlib slurp_decompress I took lzread and associated routines
from the cpio lzma support. Tested on my x86 laptop using the
following commands:
lzma e bzImage bzImage.lzma
kexec -l bzImage.lzma
Having lzma support is particularly useful on some embedded
systems on which we have the kernel already lzma compressed
and available on a mtd partition.
Signed-off-by: Florian Fainelli <florian@openwrt.org>
Signed-off-by: Simon Horman <horms@verge.net.au>
Diffstat (limited to 'kexec/zlib.c')
-rw-r--r-- | kexec/zlib.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/kexec/zlib.c b/kexec/zlib.c new file mode 100644 index 0000000..3968494 --- /dev/null +++ b/kexec/zlib.c @@ -0,0 +1,78 @@ +#include "kexec-zlib.h" +#ifdef HAVE_LIBZ +#define _GNU_SOURCE +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <ctype.h> +#include <zlib.h> + +#include "kexec.h" + +char *zlib_decompress_file(const char *filename, off_t *r_size) +{ + gzFile fp; + int errnum; + const char *msg; + char *buf; + off_t size, allocated; + ssize_t result; + + if (!filename) { + *r_size = 0; + return 0; + } + fp = gzopen(filename, "rb"); + if (fp == 0) { + msg = gzerror(fp, &errnum); + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + fprintf(stderr, "Cannot open `%s': %s\n", filename, msg); + return NULL; + } + size = 0; + allocated = 65536; + buf = xmalloc(allocated); + do { + if (size == allocated) { + allocated <<= 1; + buf = xrealloc(buf, allocated); + } + result = gzread(fp, buf + size, allocated - size); + if (result < 0) { + if ((errno == EINTR) || (errno == EAGAIN)) + continue; + + msg = gzerror(fp, &errnum); + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + die ("read on %s of %ld bytes failed: %s\n", + filename, (allocated - size) + 0UL, msg); + } + size += result; + } while(result > 0); + result = gzclose(fp); + if (result != Z_OK) { + msg = gzerror(fp, &errnum); + if (errnum == Z_ERRNO) { + msg = strerror(errno); + } + die ("Close of %s failed: %s\n", filename, msg); + } + *r_size = size; + return buf; +} +#else +char *zlib_decompress_file(const char *filename, off_t *r_size) +{ + return NULL; +} +#endif /* HAVE_ZLIB */ |