summaryrefslogtreecommitdiff
path: root/kexec/zlib.c
diff options
context:
space:
mode:
authorFlorian Fainelli <florian@openwrt.org>2009-11-19 00:17:22 +0100
committerSimon Horman <horms@verge.net.au>2009-11-30 16:06:14 +1100
commit4c2d9b93150d36d15bf75b050ed97cabd9a94774 (patch)
tree32d6b5e8180ebc0b88c3df1bdce8cf825e97e3bc /kexec/zlib.c
parentd61381a70a57a01b87afee90c976675f047d447d (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.c78
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 */