public inbox for kexec@lists.infradead.org
 help / color / mirror / Atom feed
* [PATCH] add support for loading lzma compressed kernels
@ 2009-11-15 23:53 Florian Fainelli
  2009-11-16 13:37 ` wilbur.chan
  2009-11-17  3:04 ` Simon Horman
  0 siblings, 2 replies; 10+ messages in thread
From: Florian Fainelli @ 2009-11-15 23:53 UTC (permalink / raw)
  To: kexec; +Cc: Eric W. Biederman

Hi Eric,

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>
-- 
diff -urN kexec-tools-2.0.1/configure.ac kexec-tools-2.0.1.lzma/configure.ac
--- kexec-tools-2.0.1/configure.ac	2009-08-13 01:28:04.000000000 +0200
+++ kexec-tools-2.0.1.lzma/configure.ac	2009-11-16 00:30:42.000000000 +0100
@@ -79,6 +79,9 @@
 AC_ARG_WITH([zlib], AC_HELP_STRING([--without-zlib],[disable zlib support]),
 	[ with_zlib="$withval"], [ with_zlib=yes ] )

+AC_ARG_WITH([lzma], AC_HELP_STRING([--without-lzma],[disable lzma support]),
+	[ with_lzma="$withval"], [ with_lzma=yes ] )
+
 AC_ARG_WITH([xen], AC_HELP_STRING([--without-xen],
 	[disable extended xen support]), [ with_xen="$withval"], [ with_xen=yes ] )

@@ -142,6 +145,12 @@
 		AC_MSG_NOTICE([zlib support disabled])))
 fi

+dnl See if I have a usable copy of lzma available
+if test "$with_lzma" = yes ; then
+	AC_CHECK_HEADER(lzma.h,
+		AC_CHECK_LIB(lzma, lzma_code_, ,
+		AC_MSG_NOTICE([lzma support disabled])))
+
 dnl find Xen control stack libraries
 if test "$with_xen" = yes ; then
 	AC_CHECK_HEADER(xenctrl.h,
diff -urN kexec-tools-2.0.1/include/kexec_lzma.h kexec-tools-2.0.1.lzma/include/kexec_lzma.h
--- kexec-tools-2.0.1/include/kexec_lzma.h	1970-01-01 01:00:00.000000000 +0100
+++ kexec-tools-2.0.1.lzma/include/kexec_lzma.h	2009-11-16 00:45:23.000000000 +0100
@@ -0,0 +1,24 @@
+#ifndef __KEXEC_LZMA_H
+#define __KEXEC_LZMA_H
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <lzma.h>
+
+#define kBufferSize (1 << 15)
+
+typedef struct lzfile {
+	uint8_t buf[kBufferSize];
+	lzma_stream strm;
+	FILE *file;
+	int encoding;
+	int eof;
+} LZFILE;
+
+LZFILE *lzopen(const char *path, const char *mode);
+int lzclose(LZFILE *lzfile);
+ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
+
+#endif /* __KEXEC_LZMA_H */
Files kexec-tools-2.0.1/kexec/.kexec.c.swo and kexec-tools-2.0.1.lzma/kexec/.kexec.c.swo differ
diff -urN kexec-tools-2.0.1/kexec/Makefile kexec-tools-2.0.1.lzma/kexec/Makefile
--- kexec-tools-2.0.1/kexec/Makefile	2008-10-09 00:32:14.000000000 +0200
+++ kexec-tools-2.0.1.lzma/kexec/Makefile	2009-11-15 20:36:37.000000000 +0100
@@ -22,6 +22,7 @@
 KEXEC_SRCS += kexec/crashdump.c
 KEXEC_SRCS += kexec/crashdump-xen.c
 KEXEC_SRCS += kexec/phys_arch.c
+KEXEC_SRCS += kexec/lzma.c

 KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)

diff -urN kexec-tools-2.0.1/kexec/kexec.c kexec-tools-2.0.1.lzma/kexec/kexec.c
--- kexec-tools-2.0.1/kexec/kexec.c	2009-03-18 09:38:55.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/kexec.c	2009-11-16 00:50:37.000000000 +0100
@@ -41,6 +41,9 @@
 #ifdef HAVE_LIBZ
 #include <zlib.h>
 #endif
+#ifdef HAVE_LIBLZMA
+#include <kexec_lzma.h>
+#endif
 #include <sha256.h>
 #include "kexec.h"
 #include "kexec-syscall.h"
@@ -609,6 +612,47 @@
 	*r_size =  size;
 	return buf;
 }
+#elif defined (HAVE_LIBLZMA)
+char *slurp_decompress_file(const char *filename, off_t *r_size)
+{
+	LZFILE *fp;
+	char *buf;
+	off_t size, allocated;
+	ssize_t result;
+
+	if (!filename) {
+		*r_size = 0;
+		return 0;
+	}
+	fp = lzopen(filename, "rb");
+	if (fp == 0) {
+		die("Cannot open `%s': %s\n", filename);
+	}
+	size = 0;
+	allocated = 65536;
+	buf = xmalloc(allocated);
+	do {
+		if (size == allocated) {
+			allocated <<= 1;
+			buf = xrealloc(buf, allocated);
+		}
+		result = lzread(fp, buf + size, allocated - size);
+		if (result < 0) {
+			if ((errno == EINTR) || (errno == EAGAIN))
+				continue;
+
+			die ("read on %s of %ld bytes failed\n",
+				filename, (allocated - size) + 0UL);
+		}
+		size += result;
+	} while(result > 0);
+	result = lzclose(fp);
+	if (result != LZMA_OK) {
+		die ("Close of %s failed\n", filename);
+	}
+	*r_size =  size;
+	return buf;
+}
 #else
 char *slurp_decompress_file(const char *filename, off_t *r_size)
 {
diff -urN kexec-tools-2.0.1/kexec/lzma.c kexec-tools-2.0.1.lzma/kexec/lzma.c
--- kexec-tools-2.0.1/kexec/lzma.c	1970-01-01 01:00:00.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/lzma.c	2009-11-16 00:44:56.000000000 +0100
@@ -0,0 +1,132 @@
+#include <sys/types.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <lzma.h>
+#include <kexec_lzma.h>
+
+#ifdef HAVE_LIBLZMA
+static LZFILE *lzopen_internal(const char *path, const char *mode, int fd)
+{
+	int level = 5;
+	int encoding = 0;
+	FILE *fp;
+	LZFILE *lzfile;
+	lzma_ret ret;
+	lzma_stream lzma_strm_tmp = LZMA_STREAM_INIT;
+
+	for (; *mode; mode++) {
+		if (*mode == 'w')
+			encoding = 1;
+		else if (*mode == 'r')
+			encoding = 0;
+		else if (*mode >= '1' && *mode <= '9')
+			level = *mode - '0';
+	}
+	if (fd != -1)
+		fp = fdopen(fd, encoding ? "w" : "r");
+	else
+		fp = fopen(path, encoding ? "w" : "r");
+	if (!fp)
+		return NULL;
+
+	lzfile = calloc(1, sizeof(*lzfile));
+
+	if (!lzfile) {
+		fclose(fp);
+		return NULL;
+	}
+
+	lzfile->file = fp;
+	lzfile->encoding = encoding;
+	lzfile->eof = 0;
+	lzfile->strm = lzma_strm_tmp;
+	if (encoding) {
+		lzma_options_lzma opt_lzma;
+		if (lzma_lzma_preset(&opt_lzma, level - 1))
+			return NULL;
+		ret = lzma_alone_encoder(&lzfile->strm, &opt_lzma);
+	} else {
+		ret = lzma_auto_decoder(&lzfile->strm,
+					UINT64_C(64) * 1024 * 1024, 0);
+	}
+	if (ret != LZMA_OK) {
+		fclose(fp);
+		free(lzfile);
+		return NULL;
+	}
+	return lzfile;
+}
+
+LZFILE *lzopen(const char *path, const char *mode)
+{
+	return lzopen_internal(path, mode, -1);
+}
+
+int lzclose(LZFILE *lzfile)
+{
+	lzma_ret ret;
+	int n;
+
+	if (!lzfile)
+		return -1;
+
+	if (lzfile->encoding) {
+		for (;;) {
+			lzfile->strm.avail_out = kBufferSize;
+			lzfile->strm.next_out = lzfile->buf;
+			ret = lzma_code(&lzfile->strm, LZMA_FINISH);
+			if (ret != LZMA_OK && ret != LZMA_STREAM_END)
+				return -1;
+			n = kBufferSize - lzfile->strm.avail_out;
+			if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
+				return -1;
+			if (ret == LZMA_STREAM_END)
+				break;
+		}
+	}
+	lzma_end(&lzfile->strm);
+
+	return fclose(lzfile->file);
+	free(lzfile);
+}
+
+ssize_t lzread(LZFILE *lzfile, void *buf, size_t len)
+{
+	lzma_ret ret;
+	int eof = 0;
+
+	if (!lzfile || lzfile->encoding)
+		return -1;
+
+	if (lzfile->eof)
+		return 0;
+
+	lzfile->strm.next_out = buf;
+	lzfile->strm.avail_out = len;
+
+	for (;;) {
+		if (!lzfile->strm.avail_in) {
+			lzfile->strm.next_in = lzfile->buf;
+			lzfile->strm.avail_in = fread(lzfile->buf, 1, kBufferSize, lzfile->file);
+			if (!lzfile->strm.avail_in)
+				eof = 1;
+		}
+
+		ret = lzma_code(&lzfile->strm, LZMA_RUN);
+		if (ret == LZMA_STREAM_END) {
+			lzfile->eof = 1;
+			return len - lzfile->strm.avail_out;
+		}
+
+		if (ret != LZMA_OK)
+			return -1;
+
+		if (!lzfile->strm.avail_out)
+			return len;
+
+		if (eof)
+			return -1;
+	}
+}
+#endif /* HAVE_LIBLZMA */

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-15 23:53 [PATCH] add support for loading lzma compressed kernels Florian Fainelli
@ 2009-11-16 13:37 ` wilbur.chan
  2009-11-17  3:04 ` Simon Horman
  1 sibling, 0 replies; 10+ messages in thread
From: wilbur.chan @ 2009-11-16 13:37 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: kexec

2009/11/16 Florian Fainelli <florian@openwrt.org>
>
> Hi Eric,
>
> 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.


Good.

btw, is there any solution to uImage format   ?  :D

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-15 23:53 [PATCH] add support for loading lzma compressed kernels Florian Fainelli
  2009-11-16 13:37 ` wilbur.chan
@ 2009-11-17  3:04 ` Simon Horman
  2009-11-17 14:08   ` Florian Fainelli
  1 sibling, 1 reply; 10+ messages in thread
From: Simon Horman @ 2009-11-17  3:04 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: kexec, Eric W. Biederman

On Mon, Nov 16, 2009 at 12:53:06AM +0100, Florian Fainelli wrote:
> Hi Eric,
> 
> 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>
> -- 
> diff -urN kexec-tools-2.0.1/configure.ac kexec-tools-2.0.1.lzma/configure.ac
> --- kexec-tools-2.0.1/configure.ac	2009-08-13 01:28:04.000000000 +0200
> +++ kexec-tools-2.0.1.lzma/configure.ac	2009-11-16 00:30:42.000000000 +0100
> @@ -79,6 +79,9 @@
>  AC_ARG_WITH([zlib], AC_HELP_STRING([--without-zlib],[disable zlib support]),
>  	[ with_zlib="$withval"], [ with_zlib=yes ] )
> 
> +AC_ARG_WITH([lzma], AC_HELP_STRING([--without-lzma],[disable lzma support]),
> +	[ with_lzma="$withval"], [ with_lzma=yes ] )
> +
>  AC_ARG_WITH([xen], AC_HELP_STRING([--without-xen],
>  	[disable extended xen support]), [ with_xen="$withval"], [ with_xen=yes ] )
> 
> @@ -142,6 +145,12 @@
>  		AC_MSG_NOTICE([zlib support disabled])))
>  fi
> 
> +dnl See if I have a usable copy of lzma available
> +if test "$with_lzma" = yes ; then
> +	AC_CHECK_HEADER(lzma.h,
> +		AC_CHECK_LIB(lzma, lzma_code_, ,

Should lzma_code_ be lzma_code. The former doesn't seem to work with
liblzma 4.999.9beta+20091016-1 from Debian.

> +		AC_MSG_NOTICE([lzma support disabled])))

The trailing "fi" line appears to be missing.

> +
>  dnl find Xen control stack libraries
>  if test "$with_xen" = yes ; then
>  	AC_CHECK_HEADER(xenctrl.h,
> diff -urN kexec-tools-2.0.1/include/kexec_lzma.h kexec-tools-2.0.1.lzma/include/kexec_lzma.h
> --- kexec-tools-2.0.1/include/kexec_lzma.h	1970-01-01 01:00:00.000000000 +0100
> +++ kexec-tools-2.0.1.lzma/include/kexec_lzma.h	2009-11-16 00:45:23.000000000 +0100
> @@ -0,0 +1,24 @@
> +#ifndef __KEXEC_LZMA_H
> +#define __KEXEC_LZMA_H
> +
> +#include <sys/types.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <inttypes.h>
> +#include <lzma.h>
> +
> +#define kBufferSize (1 << 15)
> +
> +typedef struct lzfile {
> +	uint8_t buf[kBufferSize];
> +	lzma_stream strm;
> +	FILE *file;
> +	int encoding;
> +	int eof;
> +} LZFILE;
> +
> +LZFILE *lzopen(const char *path, const char *mode);
> +int lzclose(LZFILE *lzfile);
> +ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
> +
> +#endif /* __KEXEC_LZMA_H */
> Files kexec-tools-2.0.1/kexec/.kexec.c.swo and kexec-tools-2.0.1.lzma/kexec/.kexec.c.swo differ
> diff -urN kexec-tools-2.0.1/kexec/Makefile kexec-tools-2.0.1.lzma/kexec/Makefile
> --- kexec-tools-2.0.1/kexec/Makefile	2008-10-09 00:32:14.000000000 +0200
> +++ kexec-tools-2.0.1.lzma/kexec/Makefile	2009-11-15 20:36:37.000000000 +0100
> @@ -22,6 +22,7 @@
>  KEXEC_SRCS += kexec/crashdump.c
>  KEXEC_SRCS += kexec/crashdump-xen.c
>  KEXEC_SRCS += kexec/phys_arch.c
> +KEXEC_SRCS += kexec/lzma.c
> 
>  KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)
> 
> diff -urN kexec-tools-2.0.1/kexec/kexec.c kexec-tools-2.0.1.lzma/kexec/kexec.c
> --- kexec-tools-2.0.1/kexec/kexec.c	2009-03-18 09:38:55.000000000 +0100
> +++ kexec-tools-2.0.1.lzma/kexec/kexec.c	2009-11-16 00:50:37.000000000 +0100
> @@ -41,6 +41,9 @@
>  #ifdef HAVE_LIBZ
>  #include <zlib.h>
>  #endif
> +#ifdef HAVE_LIBLZMA
> +#include <kexec_lzma.h>
> +#endif
>  #include <sha256.h>
>  #include "kexec.h"
>  #include "kexec-syscall.h"
> @@ -609,6 +612,47 @@
>  	*r_size =  size;
>  	return buf;
>  }
> +#elif defined (HAVE_LIBLZMA)
> +char *slurp_decompress_file(const char *filename, off_t *r_size)

Does this imply that zlib compression isn't supported if
lzma compression support is enabled?

> +{
> +	LZFILE *fp;
> +	char *buf;
> +	off_t size, allocated;
> +	ssize_t result;
> +
> +	if (!filename) {
> +		*r_size = 0;
> +		return 0;
> +	}
> +	fp = lzopen(filename, "rb");
> +	if (fp == 0) {
> +		die("Cannot open `%s': %s\n", filename);
> +	}
> +	size = 0;
> +	allocated = 65536;
> +	buf = xmalloc(allocated);
> +	do {
> +		if (size == allocated) {
> +			allocated <<= 1;
> +			buf = xrealloc(buf, allocated);
> +		}
> +		result = lzread(fp, buf + size, allocated - size);
> +		if (result < 0) {
> +			if ((errno == EINTR) || (errno == EAGAIN))
> +				continue;
> +
> +			die ("read on %s of %ld bytes failed\n",
> +				filename, (allocated - size) + 0UL);
> +		}
> +		size += result;
> +	} while(result > 0);
> +	result = lzclose(fp);
> +	if (result != LZMA_OK) {
> +		die ("Close of %s failed\n", filename);
> +	}
> +	*r_size =  size;
> +	return buf;
> +}
>  #else
>  char *slurp_decompress_file(const char *filename, off_t *r_size)
>  {
> diff -urN kexec-tools-2.0.1/kexec/lzma.c kexec-tools-2.0.1.lzma/kexec/lzma.c
> --- kexec-tools-2.0.1/kexec/lzma.c	1970-01-01 01:00:00.000000000 +0100
> +++ kexec-tools-2.0.1.lzma/kexec/lzma.c	2009-11-16 00:44:56.000000000 +0100
> @@ -0,0 +1,132 @@
> +#include <sys/types.h>
> +#include <inttypes.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <lzma.h>
> +#include <kexec_lzma.h>
> +
> +#ifdef HAVE_LIBLZMA

#include <kexec_lzma.h> needs to be inside HAVE_LIBLZMA,
it seems just as well to move the #ifdef to the top of the file.

> +static LZFILE *lzopen_internal(const char *path, const char *mode, int fd)
> +{
> +	int level = 5;
> +	int encoding = 0;
> +	FILE *fp;
> +	LZFILE *lzfile;
> +	lzma_ret ret;
> +	lzma_stream lzma_strm_tmp = LZMA_STREAM_INIT;
> +
> +	for (; *mode; mode++) {
> +		if (*mode == 'w')
> +			encoding = 1;
> +		else if (*mode == 'r')
> +			encoding = 0;
> +		else if (*mode >= '1' && *mode <= '9')
> +			level = *mode - '0';
> +	}
> +	if (fd != -1)
> +		fp = fdopen(fd, encoding ? "w" : "r");
> +	else
> +		fp = fopen(path, encoding ? "w" : "r");
> +	if (!fp)
> +		return NULL;
> +
> +	lzfile = calloc(1, sizeof(*lzfile));
> +
> +	if (!lzfile) {
> +		fclose(fp);
> +		return NULL;
> +	}
> +
> +	lzfile->file = fp;
> +	lzfile->encoding = encoding;
> +	lzfile->eof = 0;
> +	lzfile->strm = lzma_strm_tmp;
> +	if (encoding) {
> +		lzma_options_lzma opt_lzma;
> +		if (lzma_lzma_preset(&opt_lzma, level - 1))
> +			return NULL;
> +		ret = lzma_alone_encoder(&lzfile->strm, &opt_lzma);
> +	} else {
> +		ret = lzma_auto_decoder(&lzfile->strm,
> +					UINT64_C(64) * 1024 * 1024, 0);
> +	}
> +	if (ret != LZMA_OK) {
> +		fclose(fp);
> +		free(lzfile);
> +		return NULL;
> +	}
> +	return lzfile;
> +}
> +
> +LZFILE *lzopen(const char *path, const char *mode)
> +{
> +	return lzopen_internal(path, mode, -1);
> +}
> +
> +int lzclose(LZFILE *lzfile)
> +{
> +	lzma_ret ret;
> +	int n;
> +
> +	if (!lzfile)
> +		return -1;
> +
> +	if (lzfile->encoding) {
> +		for (;;) {
> +			lzfile->strm.avail_out = kBufferSize;
> +			lzfile->strm.next_out = lzfile->buf;
> +			ret = lzma_code(&lzfile->strm, LZMA_FINISH);
> +			if (ret != LZMA_OK && ret != LZMA_STREAM_END)
> +				return -1;
> +			n = kBufferSize - lzfile->strm.avail_out;
> +			if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
> +				return -1;
> +			if (ret == LZMA_STREAM_END)
> +				break;
> +		}
> +	}
> +	lzma_end(&lzfile->strm);
> +
> +	return fclose(lzfile->file);
> +	free(lzfile);
> +}
> +
> +ssize_t lzread(LZFILE *lzfile, void *buf, size_t len)
> +{
> +	lzma_ret ret;
> +	int eof = 0;
> +
> +	if (!lzfile || lzfile->encoding)
> +		return -1;
> +
> +	if (lzfile->eof)
> +		return 0;
> +
> +	lzfile->strm.next_out = buf;
> +	lzfile->strm.avail_out = len;
> +
> +	for (;;) {
> +		if (!lzfile->strm.avail_in) {
> +			lzfile->strm.next_in = lzfile->buf;
> +			lzfile->strm.avail_in = fread(lzfile->buf, 1, kBufferSize, lzfile->file);
> +			if (!lzfile->strm.avail_in)
> +				eof = 1;
> +		}
> +
> +		ret = lzma_code(&lzfile->strm, LZMA_RUN);
> +		if (ret == LZMA_STREAM_END) {
> +			lzfile->eof = 1;
> +			return len - lzfile->strm.avail_out;
> +		}
> +
> +		if (ret != LZMA_OK)
> +			return -1;
> +
> +		if (!lzfile->strm.avail_out)
> +			return len;
> +
> +		if (eof)
> +			return -1;
> +	}
> +}
> +#endif /* HAVE_LIBLZMA */
> 
> _______________________________________________
> kexec mailing list
> kexec@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-17  3:04 ` Simon Horman
@ 2009-11-17 14:08   ` Florian Fainelli
  2009-11-17 14:23     ` Florian Fainelli
  0 siblings, 1 reply; 10+ messages in thread
From: Florian Fainelli @ 2009-11-17 14:08 UTC (permalink / raw)
  To: kexec; +Cc: Simon Horman, Eric W. Biederman

Hello Simon,

On Tuesday 17 November 2009 04:04:38 Simon Horman wrote:
> On Mon, Nov 16, 2009 at 12:53:06AM +0100, Florian Fainelli wrote:
> > Hi Eric,
> >
> > 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>
> 
> Should lzma_code_ be lzma_code. The former doesn't seem to work with
> liblzma 4.999.9beta+20091016-1 from Debian.

You are right it's actually lzma_code (without the trailing _).

> 
> > +		AC_MSG_NOTICE([lzma support disabled])))
> 
> The trailing "fi" line appears to be missing.

Fixed too.
[snip]

> Does this imply that zlib compression isn't supported if
> lzma compression support is enabled?

Indeed, we might want to support both at runtime. Would you agree with the 
following proposal:

- rename slurp_decompress_file to zlib/lzma_decompress_file
- in case gzopen fails, do not die, but return NULL
- test the return value of zlib_decompress_file and try lzma_decompress_file

> 
> > +{
> > +	LZFILE *fp;
> > +	char *buf;
> > +	off_t size, allocated;
> > +	ssize_t result;
> > +
> > +	if (!filename) {
> > +		*r_size = 0;
> > +		return 0;
> > +	}
> > +	fp = lzopen(filename, "rb");
> > +	if (fp == 0) {
> > +		die("Cannot open `%s': %s\n", filename);
> > +	}
> > +	size = 0;
> > +	allocated = 65536;
> > +	buf = xmalloc(allocated);
> > +	do {
> > +		if (size == allocated) {
> > +			allocated <<= 1;
> > +			buf = xrealloc(buf, allocated);
> > +		}
> > +		result = lzread(fp, buf + size, allocated - size);
> > +		if (result < 0) {
> > +			if ((errno == EINTR) || (errno == EAGAIN))
> > +				continue;
> > +
> > +			die ("read on %s of %ld bytes failed\n",
> > +				filename, (allocated - size) + 0UL);
> > +		}
> > +		size += result;
> > +	} while(result > 0);
> > +	result = lzclose(fp);
> > +	if (result != LZMA_OK) {
> > +		die ("Close of %s failed\n", filename);
> > +	}
> > +	*r_size =  size;
> > +	return buf;
> > +}
> >  #else
> >  char *slurp_decompress_file(const char *filename, off_t *r_size)
> >  {
> > diff -urN kexec-tools-2.0.1/kexec/lzma.c
> > kexec-tools-2.0.1.lzma/kexec/lzma.c ---
> > kexec-tools-2.0.1/kexec/lzma.c	1970-01-01 01:00:00.000000000 +0100 +++
> > kexec-tools-2.0.1.lzma/kexec/lzma.c	2009-11-16 00:44:56.000000000 +0100
> > @@ -0,0 +1,132 @@
> > +#include <sys/types.h>
> > +#include <inttypes.h>
> > +#include <string.h>
> > +#include <stdlib.h>
> > +#include <lzma.h>
> > +#include <kexec_lzma.h>
> > +
> > +#ifdef HAVE_LIBLZMA
> 
> #include <kexec_lzma.h> needs to be inside HAVE_LIBLZMA,
> it seems just as well to move the #ifdef to the top of the file.

Fixed.
--
WBR, Florian

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-17 14:08   ` Florian Fainelli
@ 2009-11-17 14:23     ` Florian Fainelli
  2009-11-18  3:55       ` Simon Horman
  0 siblings, 1 reply; 10+ messages in thread
From: Florian Fainelli @ 2009-11-17 14:23 UTC (permalink / raw)
  To: kexec; +Cc: Simon Horman, Eric W. Biederman

On Tuesday 17 November 2009 15:08:29 Florian Fainelli wrote:
> Hello Simon,
> 
> On Tuesday 17 November 2009 04:04:38 Simon Horman wrote:
> > On Mon, Nov 16, 2009 at 12:53:06AM +0100, Florian Fainelli wrote:
> > > Hi Eric,
> > >
> > > 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>
> >
> > Should lzma_code_ be lzma_code. The former doesn't seem to work with
> > liblzma 4.999.9beta+20091016-1 from Debian.
> 
> You are right it's actually lzma_code (without the trailing _).
> 
> > > +		AC_MSG_NOTICE([lzma support disabled])))
> >
> > The trailing "fi" line appears to be missing.
> 
> Fixed too.
> [snip]
> 
> > Does this imply that zlib compression isn't supported if
> > lzma compression support is enabled?
> 
> Indeed, we might want to support both at runtime. Would you agree with the
> following proposal:
> 
> - rename slurp_decompress_file to zlib/lzma_decompress_file
> - in case gzopen fails, do not die, but return NULL
> - test the return value of zlib_decompress_file and try
>  lzma_decompress_file

We would also have to modify the call sites of slurp_decompress file this might 
become pretty heavy if we support more decompression algorithms. What do you 
think?
--
WBR, Florian

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-17 14:23     ` Florian Fainelli
@ 2009-11-18  3:55       ` Simon Horman
  2009-11-18 23:17         ` Florian Fainelli
  0 siblings, 1 reply; 10+ messages in thread
From: Simon Horman @ 2009-11-18  3:55 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: kexec, Eric W. Biederman

On Tue, Nov 17, 2009 at 03:23:15PM +0100, Florian Fainelli wrote:
> On Tuesday 17 November 2009 15:08:29 Florian Fainelli wrote:
> > Hello Simon,
> > 
> > On Tuesday 17 November 2009 04:04:38 Simon Horman wrote:
> > > On Mon, Nov 16, 2009 at 12:53:06AM +0100, Florian Fainelli wrote:
> > > > Hi Eric,
> > > >
> > > > 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>
> > >
> > > Should lzma_code_ be lzma_code. The former doesn't seem to work with
> > > liblzma 4.999.9beta+20091016-1 from Debian.
> > 
> > You are right it's actually lzma_code (without the trailing _).
> > 
> > > > +		AC_MSG_NOTICE([lzma support disabled])))
> > >
> > > The trailing "fi" line appears to be missing.
> > 
> > Fixed too.
> > [snip]
> > 
> > > Does this imply that zlib compression isn't supported if
> > > lzma compression support is enabled?
> > 
> > Indeed, we might want to support both at runtime. Would you agree with the
> > following proposal:
> > 
> > - rename slurp_decompress_file to zlib/lzma_decompress_file
> > - in case gzopen fails, do not die, but return NULL
> > - test the return value of zlib_decompress_file and try
> >  lzma_decompress_file

      Something along those lines sounds entirely reasonable to me.

> We would also have to modify the call sites of slurp_decompress file this might 
> become pretty heavy if we support more decompression algorithms. What do you 
> think?

Perhaps slurp_decompress could be a wrapper which tries each algorithm in
turn as necessary?

Also, I'd like to get rid of the #ifdef around what is currently
slurp_decompress_file() if possible. My idea would be to move
zlib_decompress_file and lzma_decompress_file into, for instance
zlib.c and lzma.c respectively and have zlib.h and lzma.h provide
more-or-less null functions for the case where the algorithm
in question isn't supported.


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-18  3:55       ` Simon Horman
@ 2009-11-18 23:17         ` Florian Fainelli
  2009-11-19  0:03           ` Eric W. Biederman
  0 siblings, 1 reply; 10+ messages in thread
From: Florian Fainelli @ 2009-11-18 23:17 UTC (permalink / raw)
  To: Simon Horman; +Cc: kexec, Eric W. Biederman

Hello Simon,

Le mercredi 18 novembre 2009 04:55:18, Simon Horman a écrit :
> On Tue, Nov 17, 2009 at 03:23:15PM +0100, Florian Fainelli wrote:
> > On Tuesday 17 November 2009 15:08:29 Florian Fainelli wrote:
> > > Hello Simon,
> > >
> > > On Tuesday 17 November 2009 04:04:38 Simon Horman wrote:
> > > > On Mon, Nov 16, 2009 at 12:53:06AM +0100, Florian Fainelli wrote:
> > > > > Hi Eric,
> > > > >
> > > > > 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>
> > > >
> > > > Should lzma_code_ be lzma_code. The former doesn't seem to work with
> > > > liblzma 4.999.9beta+20091016-1 from Debian.
> > >
> > > You are right it's actually lzma_code (without the trailing _).
> > >
> > > > > +		AC_MSG_NOTICE([lzma support disabled])))
> > > >
> > > > The trailing "fi" line appears to be missing.
> > >
> > > Fixed too.
> > > [snip]
> > >
> > > > Does this imply that zlib compression isn't supported if
> > > > lzma compression support is enabled?
> > >
> > > Indeed, we might want to support both at runtime. Would you agree with
> > > the following proposal:
> > >
> > > - rename slurp_decompress_file to zlib/lzma_decompress_file
> > > - in case gzopen fails, do not die, but return NULL
> > > - test the return value of zlib_decompress_file and try
> > >  lzma_decompress_file
> 
>       Something along those lines sounds entirely reasonable to me.
> 
> > We would also have to modify the call sites of slurp_decompress file this
> > might become pretty heavy if we support more decompression algorithms.
> > What do you think?
> 
> Perhaps slurp_decompress could be a wrapper which tries each algorithm in
> turn as necessary?
> 
> Also, I'd like to get rid of the #ifdef around what is currently
> slurp_decompress_file() if possible. My idea would be to move
> zlib_decompress_file and lzma_decompress_file into, for instance
> zlib.c and lzma.c respectively and have zlib.h and lzma.h provide
> more-or-less null functions for the case where the algorithm
> in question isn't supported.

Please find below a version which should address your comments.
Thanks for reviewing the patch.
--
From: Florian Fainelli <florian@openwrt.org>
Subject: [PATCH] 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>
---
diff -urN kexec-tools-2.0.1/configure.ac kexec-tools-2.0.1.lzma/configure.ac
--- kexec-tools-2.0.1/configure.ac	2009-11-18 23:11:36.000000000 +0100
+++ kexec-tools-2.0.1.lzma/configure.ac	2009-11-18 23:11:21.000000000 +0100
@@ -79,6 +79,9 @@
 AC_ARG_WITH([zlib], AC_HELP_STRING([--without-zlib],[disable zlib support]),
 	[ with_zlib="$withval"], [ with_zlib=yes ] )
 
+AC_ARG_WITH([lzma], AC_HELP_STRING([--without-lzma],[disable lzma support]),
+	[ with_lzma="$withval"], [ with_lzma=yes ] )
+
 AC_ARG_WITH([xen], AC_HELP_STRING([--without-xen],
 	[disable extended xen support]), [ with_xen="$withval"], [ with_xen=yes ] )
 
@@ -142,6 +145,13 @@
 		AC_MSG_NOTICE([zlib support disabled])))
 fi
 
+dnl See if I have a usable copy of lzma available
+if test "$with_lzma" = yes ; then
+	AC_CHECK_HEADER(lzma.h,
+		AC_CHECK_LIB(lzma, lzma_code, ,
+		AC_MSG_NOTICE([lzma support disabled])))
+fi
+
 dnl find Xen control stack libraries
 if test "$with_xen" = yes ; then
 	AC_CHECK_HEADER(xenctrl.h,
diff -urN kexec-tools-2.0.1/kexec/Makefile kexec-tools-2.0.1.lzma/kexec/Makefile
--- kexec-tools-2.0.1/kexec/Makefile	2009-11-18 23:11:37.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/Makefile	2009-11-18 23:15:21.000000000 +0100
@@ -22,6 +22,8 @@
 KEXEC_SRCS += kexec/crashdump.c
 KEXEC_SRCS += kexec/crashdump-xen.c
 KEXEC_SRCS += kexec/phys_arch.c
+KEXEC_SRCS += kexec/lzma.c
+KEXEC_SRCS += kexec/zlib.c
 
 KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)
 
diff -urN kexec-tools-2.0.1/kexec/kexec-lzma.h kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h
--- kexec-tools-2.0.1/kexec/kexec-lzma.h	1970-01-01 01:00:00.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h	2009-11-19 00:06:24.000000000 +0100
@@ -0,0 +1,29 @@
+#ifndef __KEXEC_LZMA_H
+#define __KEXEC_LZMA_H
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <lzma.h>
+
+#include "config.h"
+
+#ifdef HAVE_LIBLZMA
+#define kBufferSize (1 << 15)
+
+typedef struct lzfile {
+	uint8_t buf[kBufferSize];
+	lzma_stream strm;
+	FILE *file;
+	int encoding;
+	int eof;
+} LZFILE;
+
+LZFILE *lzopen(const char *path, const char *mode);
+int lzclose(LZFILE *lzfile);
+ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
+#endif /* HAVE_LIBLZMA */
+
+char *lzma_decompress_file(const char *filename, off_t *r_size);
+#endif /* __KEXEC_LZMA_H */
diff -urN kexec-tools-2.0.1/kexec/kexec-zlib.h kexec-tools-2.0.1.lzma/kexec/kexec-zlib.h
--- kexec-tools-2.0.1/kexec/kexec-zlib.h	1970-01-01 01:00:00.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/kexec-zlib.h	2009-11-19 00:04:38.000000000 +0100
@@ -0,0 +1,10 @@
+#ifndef __KEXEC_ZLIB_H
+#define __KEXEC_ZLIB_H
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+char *zlib_decompress_file(const char *filename, off_t *r_size);
+#endif /* __KEXEC_ZLIB_H */
diff -urN kexec-tools-2.0.1/kexec/kexec.c kexec-tools-2.0.1.lzma/kexec/kexec.c
--- kexec-tools-2.0.1/kexec/kexec.c	2009-11-18 23:11:45.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/kexec.c	2009-11-18 23:19:46.000000000 +0100
@@ -38,14 +38,13 @@
 
 #include "config.h"
 
-#ifdef HAVE_LIBZ
-#include <zlib.h>
-#endif
 #include <sha256.h>
 #include "kexec.h"
 #include "kexec-syscall.h"
 #include "kexec-elf.h"
 #include "kexec-sha256.h"
+#include "kexec-zlib.h"
+#include "kexec-lzma.h"
 #include <arch/options.h>
 
 unsigned long long mem_min = 0;
@@ -554,67 +553,18 @@
 	return buf;
 }
 
-#if HAVE_LIBZ
 char *slurp_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);
-		}
-		die("Cannot open `%s': %s\n", filename, msg);
-	}
-	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;
+	char *kernel_buf;
 
-			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);
+	kernel_buf = zlib_decompress_file(filename, r_size);
+	if (!kernel_buf) {
+		kernel_buf = lzma_decompress_file(filename, r_size);
+		if (!kernel_buf)
+			return slurp_file(filename, r_size);
 	}
-	*r_size =  size;
-	return buf;
+	return kernel_buf;
 }
-#else
-char *slurp_decompress_file(const char *filename, off_t *r_size)
-{
-	return slurp_file(filename, r_size);
-}
-#endif
 
 static void update_purgatory(struct kexec_info *info)
 {
diff -urN kexec-tools-2.0.1/kexec/lzma.c kexec-tools-2.0.1.lzma/kexec/lzma.c
--- kexec-tools-2.0.1/kexec/lzma.c	1970-01-01 01:00:00.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/lzma.c	2009-11-19 00:03:54.000000000 +0100
@@ -0,0 +1,187 @@
+#include "kexec-lzma.h"
+#ifdef HAVE_LIBLZMA
+#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 <lzma.h>
+
+#include "kexec.h"
+
+static LZFILE *lzopen_internal(const char *path, const char *mode, int fd)
+{
+	int level = 5;
+	int encoding = 0;
+	FILE *fp;
+	LZFILE *lzfile;
+	lzma_ret ret;
+	lzma_stream lzma_strm_tmp = LZMA_STREAM_INIT;
+
+	for (; *mode; mode++) {
+		if (*mode == 'w')
+			encoding = 1;
+		else if (*mode == 'r')
+			encoding = 0;
+		else if (*mode >= '1' && *mode <= '9')
+			level = *mode - '0';
+	}
+	if (fd != -1)
+		fp = fdopen(fd, encoding ? "w" : "r");
+	else
+		fp = fopen(path, encoding ? "w" : "r");
+	if (!fp)
+		return NULL;
+
+	lzfile = calloc(1, sizeof(*lzfile));
+
+	if (!lzfile) {
+		fclose(fp);
+		return NULL;
+	}
+
+	lzfile->file = fp;
+	lzfile->encoding = encoding;
+	lzfile->eof = 0;
+	lzfile->strm = lzma_strm_tmp;
+	if (encoding) {
+		lzma_options_lzma opt_lzma;
+		if (lzma_lzma_preset(&opt_lzma, level - 1))
+			return NULL;
+		ret = lzma_alone_encoder(&lzfile->strm, &opt_lzma);
+	} else {
+		ret = lzma_auto_decoder(&lzfile->strm,
+					UINT64_C(64) * 1024 * 1024, 0);
+	}
+	if (ret != LZMA_OK) {
+		fclose(fp);
+		free(lzfile);
+		return NULL;
+	}
+	return lzfile;
+}
+
+LZFILE *lzopen(const char *path, const char *mode)
+{
+	return lzopen_internal(path, mode, -1);
+}
+
+int lzclose(LZFILE *lzfile)
+{
+	lzma_ret ret;
+	int n;
+
+	if (!lzfile)
+		return -1;
+
+	if (lzfile->encoding) {
+		for (;;) {
+			lzfile->strm.avail_out = kBufferSize;
+			lzfile->strm.next_out = lzfile->buf;
+			ret = lzma_code(&lzfile->strm, LZMA_FINISH);
+			if (ret != LZMA_OK && ret != LZMA_STREAM_END)
+				return -1;
+			n = kBufferSize - lzfile->strm.avail_out;
+			if (n && fwrite(lzfile->buf, 1, n, lzfile->file) != n)
+				return -1;
+			if (ret == LZMA_STREAM_END)
+				break;
+		}
+	}
+	lzma_end(&lzfile->strm);
+
+	return fclose(lzfile->file);
+	free(lzfile);
+}
+
+ssize_t lzread(LZFILE *lzfile, void *buf, size_t len)
+{
+	lzma_ret ret;
+	int eof = 0;
+
+	if (!lzfile || lzfile->encoding)
+		return -1;
+
+	if (lzfile->eof)
+		return 0;
+
+	lzfile->strm.next_out = buf;
+	lzfile->strm.avail_out = len;
+
+	for (;;) {
+		if (!lzfile->strm.avail_in) {
+			lzfile->strm.next_in = lzfile->buf;
+			lzfile->strm.avail_in = fread(lzfile->buf, 1, kBufferSize, lzfile->file);
+			if (!lzfile->strm.avail_in)
+				eof = 1;
+		}
+
+		ret = lzma_code(&lzfile->strm, LZMA_RUN);
+		if (ret == LZMA_STREAM_END) {
+			lzfile->eof = 1;
+			return len - lzfile->strm.avail_out;
+		}
+
+		if (ret != LZMA_OK)
+			return -1;
+
+		if (!lzfile->strm.avail_out)
+			return len;
+
+		if (eof)
+			return -1;
+	}
+}
+
+char *lzma_decompress_file(const char *filename, off_t *r_size)
+{
+	LZFILE *fp;
+	char *buf;
+	off_t size, allocated;
+	ssize_t result;
+
+	if (!filename) {
+		*r_size = 0;
+		return 0;
+	}
+	fp = lzopen(filename, "rb");
+	if (fp == 0) {
+		die("Cannot open `%s': %s\n", filename);
+	}
+	size = 0;
+	allocated = 65536;
+	buf = xmalloc(allocated);
+	do {
+		if (size == allocated) {
+			allocated <<= 1;
+			buf = xrealloc(buf, allocated);
+		}
+		result = lzread(fp, buf + size, allocated - size);
+		if (result < 0) {
+			if ((errno == EINTR) || (errno == EAGAIN))
+				continue;
+
+			die ("read on %s of %ld bytes failed\n",
+				filename, (allocated - size) + 0UL);
+		}
+		size += result;
+	} while(result > 0);
+	result = lzclose(fp);
+	if (result != LZMA_OK) {
+		die ("Close of %s failed\n", filename);
+	}
+	*r_size =  size;
+	return buf;
+}
+#else
+char *lzma_decompress_file(const char *filename, off_t *r_size)
+{
+	return NULL;
+}
+#endif /* HAVE_LIBLZMA */
diff -urN kexec-tools-2.0.1/kexec/zlib.c kexec-tools-2.0.1.lzma/kexec/zlib.c
--- kexec-tools-2.0.1/kexec/zlib.c	1970-01-01 01:00:00.000000000 +0100
+++ kexec-tools-2.0.1.lzma/kexec/zlib.c	2009-11-19 00:05:28.000000000 +0100
@@ -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 */

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-18 23:17         ` Florian Fainelli
@ 2009-11-19  0:03           ` Eric W. Biederman
  2009-11-30  5:51             ` Simon Horman
  0 siblings, 1 reply; 10+ messages in thread
From: Eric W. Biederman @ 2009-11-19  0:03 UTC (permalink / raw)
  To: Florian Fainelli; +Cc: Simon Horman, kexec

Florian Fainelli <florian@openwrt.org> writes:

> Please find below a version which should address your comments.
> Thanks for reviewing the patch.
> --
> From: Florian Fainelli <florian@openwrt.org>
> Subject: [PATCH] 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.

Yes.  I don't think it is particularly useful on x86 (as we have
a decompressor built into the kernel) but on other arches
it makes a lot of sense.

A few minor comments inline.

> diff -urN kexec-tools-2.0.1/kexec/kexec-lzma.h kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h
> --- kexec-tools-2.0.1/kexec/kexec-lzma.h	1970-01-01 01:00:00.000000000 +0100
> +++ kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h	2009-11-19 00:06:24.000000000 +0100
> @@ -0,0 +1,29 @@
> +#ifndef __KEXEC_LZMA_H
> +#define __KEXEC_LZMA_H
> +
> +#include <stdio.h>
> +#include <sys/types.h>
> +#include <unistd.h>
> +#include <inttypes.h>
> +#include <lzma.h>
> +
> +#include "config.h"
> +
> +#ifdef HAVE_LIBLZMA
> +#define kBufferSize (1 << 15)
> +
> +typedef struct lzfile {
> +	uint8_t buf[kBufferSize];
> +	lzma_stream strm;
> +	FILE *file;
> +	int encoding;
> +	int eof;
> +} LZFILE;
> +
> +LZFILE *lzopen(const char *path, const char *mode);
> +int lzclose(LZFILE *lzfile);
> +ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);

I don't think we need any of these definitions in the header file.

> +#endif /* HAVE_LIBLZMA */
> +
> +char *lzma_decompress_file(const char *filename, off_t *r_size);

Ideally the lzma_decompress_file stub would live here and would not
even compile kexec/lzma.c if we don't have lzma.

> +#endif /* __KEXEC_LZMA_H */


Eric

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-19  0:03           ` Eric W. Biederman
@ 2009-11-30  5:51             ` Simon Horman
  2009-11-30 10:08               ` Florian Fainelli
  0 siblings, 1 reply; 10+ messages in thread
From: Simon Horman @ 2009-11-30  5:51 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: kexec, Florian Fainelli

On Wed, Nov 18, 2009 at 04:03:27PM -0800, Eric W. Biederman wrote:
> Florian Fainelli <florian@openwrt.org> writes:
> 
> > Please find below a version which should address your comments.
> > Thanks for reviewing the patch.

Thanks, Applied.

> > --
> > From: Florian Fainelli <florian@openwrt.org>
> > Subject: [PATCH] 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.
> 
> Yes.  I don't think it is particularly useful on x86 (as we have
> a decompressor built into the kernel) but on other arches
> it makes a lot of sense.
> 
> A few minor comments inline.
> 
> > diff -urN kexec-tools-2.0.1/kexec/kexec-lzma.h kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h
> > --- kexec-tools-2.0.1/kexec/kexec-lzma.h	1970-01-01 01:00:00.000000000 +0100
> > +++ kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h	2009-11-19 00:06:24.000000000 +0100
> > @@ -0,0 +1,29 @@
> > +#ifndef __KEXEC_LZMA_H
> > +#define __KEXEC_LZMA_H
> > +
> > +#include <stdio.h>
> > +#include <sys/types.h>
> > +#include <unistd.h>
> > +#include <inttypes.h>
> > +#include <lzma.h>
> > +
> > +#include "config.h"
> > +
> > +#ifdef HAVE_LIBLZMA
> > +#define kBufferSize (1 << 15)
> > +
> > +typedef struct lzfile {
> > +	uint8_t buf[kBufferSize];
> > +	lzma_stream strm;
> > +	FILE *file;
> > +	int encoding;
> > +	int eof;
> > +} LZFILE;
> > +
> > +LZFILE *lzopen(const char *path, const char *mode);
> > +int lzclose(LZFILE *lzfile);
> > +ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
> 
> I don't think we need any of these definitions in the header file.
> 
> > +#endif /* HAVE_LIBLZMA */
> > +
> > +char *lzma_decompress_file(const char *filename, off_t *r_size);
> 
> Ideally the lzma_decompress_file stub would live here and would not
> even compile kexec/lzma.c if we don't have lzma.
> 
> > +#endif /* __KEXEC_LZMA_H */

I have also applied the following change

----------------------------------------------------------------------

lzma: Move the bulk of kexec-lzma.h into lzma.c

There isn't any need for anything in kexec-lzma.h other
than a declaration of zlib_decompress_file().

Other being cleaner it also fixes a build problem when
lzma support isn't being compiled in.

$ make all
i686-unknown-linux-gnu-gcc -Wall -Wextra -O2 -fomit-frame-pointer -pipe -fno-strict-aliasing -Wall -Wstrict-prototypes -I/home/horms/local/opt/crosstool/i686/gcc-3.4.5-glibc-2.3.6/i686-unknown-linux-gnu/include -I./include -I./util_lib/include -Iinclude/ -I./kexec/arch/i386/include  -c
-MD -o kexec/kexec.o kexec/kexec.c
In file included from kexec/kexec.c:47:
kexec/kexec-lzma.h:8:18: lzma.h: No such file or directory
kexec/kexec.c: In function `locate_hole':
kexec/kexec.c:203: warning: comparison between signed and unsigned

It ought to be possible to just provide a stub for zlib_decompress_file()
in kexec-lzma.h and not compile lzma.c at all in the case where
lzma support isn't being compiled in. However I see no obvious way
to do this with the existing build system. So I'd like to deal
with that as a separate possible change.

Changes as suggested by Eric W. Biederman.

Cc: Florian Fainelli <florian@openwrt.org>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Simon Horman <horms@verge.net.au>

Index: kexec-tools/kexec/kexec-lzma.h
===================================================================
--- kexec-tools.orig/kexec/kexec-lzma.h	2009-11-30 16:43:38.000000000 +1100
+++ kexec-tools/kexec/kexec-lzma.h	2009-11-30 16:44:15.000000000 +1100
@@ -1,29 +1,8 @@
 #ifndef __KEXEC_LZMA_H
 #define __KEXEC_LZMA_H
 
-#include <stdio.h>
 #include <sys/types.h>
-#include <unistd.h>
-#include <inttypes.h>
-#include <lzma.h>
-
-#include "config.h"
-
-#ifdef HAVE_LIBLZMA
-#define kBufferSize (1 << 15)
-
-typedef struct lzfile {
-	uint8_t buf[kBufferSize];
-	lzma_stream strm;
-	FILE *file;
-	int encoding;
-	int eof;
-} LZFILE;
-
-LZFILE *lzopen(const char *path, const char *mode);
-int lzclose(LZFILE *lzfile);
-ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
-#endif /* HAVE_LIBLZMA */
 
 char *lzma_decompress_file(const char *filename, off_t *r_size);
+
 #endif /* __KEXEC_LZMA_H */
Index: kexec-tools/kexec/lzma.c
===================================================================
--- kexec-tools.orig/kexec/lzma.c	2009-11-30 16:43:38.000000000 +1100
+++ kexec-tools/kexec/lzma.c	2009-11-30 16:44:15.000000000 +1100
@@ -1,4 +1,9 @@
+#include <unistd.h>
+#include <sys/types.h>
+
 #include "kexec-lzma.h"
+#include "config.h"
+
 #ifdef HAVE_LIBLZMA
 #define _GNU_SOURCE
 #include <stdio.h>
@@ -7,14 +12,26 @@
 #include <stdlib.h>
 #include <errno.h>
 #include <limits.h>
-#include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <ctype.h>
 #include <lzma.h>
 
 #include "kexec.h"
 
+#define kBufferSize (1 << 15)
+
+typedef struct lzfile {
+	uint8_t buf[kBufferSize];
+	lzma_stream strm;
+	FILE *file;
+	int encoding;
+	int eof;
+} LZFILE;
+
+LZFILE *lzopen(const char *path, const char *mode);
+int lzclose(LZFILE *lzfile);
+ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
+
 static LZFILE *lzopen_internal(const char *path, const char *mode, int fd)
 {
 	int level = 5;

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] add support for loading lzma compressed kernels
  2009-11-30  5:51             ` Simon Horman
@ 2009-11-30 10:08               ` Florian Fainelli
  0 siblings, 0 replies; 10+ messages in thread
From: Florian Fainelli @ 2009-11-30 10:08 UTC (permalink / raw)
  To: Simon Horman; +Cc: kexec, Eric W. Biederman

Hello Simon,

On Monday 30 November 2009 06:51:39 Simon Horman wrote:
> On Wed, Nov 18, 2009 at 04:03:27PM -0800, Eric W. Biederman wrote:
> > Florian Fainelli <florian@openwrt.org> writes:
> > > Please find below a version which should address your comments.
> > > Thanks for reviewing the patch.
> 
> Thanks, Applied.

Oh thanks, I was about to respin with the changes Eric suggested.

> 
> > > --
> > > From: Florian Fainelli <florian@openwrt.org>
> > > Subject: [PATCH] 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.
> >
> > Yes.  I don't think it is particularly useful on x86 (as we have
> > a decompressor built into the kernel) but on other arches
> > it makes a lot of sense.
> >
> > A few minor comments inline.
> >
> > > diff -urN kexec-tools-2.0.1/kexec/kexec-lzma.h
> > > kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h ---
> > > kexec-tools-2.0.1/kexec/kexec-lzma.h	1970-01-01 01:00:00.000000000
> > > +0100 +++ kexec-tools-2.0.1.lzma/kexec/kexec-lzma.h	2009-11-19
> > > 00:06:24.000000000 +0100 @@ -0,0 +1,29 @@
> > > +#ifndef __KEXEC_LZMA_H
> > > +#define __KEXEC_LZMA_H
> > > +
> > > +#include <stdio.h>
> > > +#include <sys/types.h>
> > > +#include <unistd.h>
> > > +#include <inttypes.h>
> > > +#include <lzma.h>
> > > +
> > > +#include "config.h"
> > > +
> > > +#ifdef HAVE_LIBLZMA
> > > +#define kBufferSize (1 << 15)
> > > +
> > > +typedef struct lzfile {
> > > +	uint8_t buf[kBufferSize];
> > > +	lzma_stream strm;
> > > +	FILE *file;
> > > +	int encoding;
> > > +	int eof;
> > > +} LZFILE;
> > > +
> > > +LZFILE *lzopen(const char *path, const char *mode);
> > > +int lzclose(LZFILE *lzfile);
> > > +ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
> >
> > I don't think we need any of these definitions in the header file.
> >
> > > +#endif /* HAVE_LIBLZMA */
> > > +
> > > +char *lzma_decompress_file(const char *filename, off_t *r_size);
> >
> > Ideally the lzma_decompress_file stub would live here and would not
> > even compile kexec/lzma.c if we don't have lzma.
> >
> > > +#endif /* __KEXEC_LZMA_H */
> 
> I have also applied the following change
> 
> ----------------------------------------------------------------------
> 
> lzma: Move the bulk of kexec-lzma.h into lzma.c
> 
> There isn't any need for anything in kexec-lzma.h other
> than a declaration of zlib_decompress_file().
> 
> Other being cleaner it also fixes a build problem when
> lzma support isn't being compiled in.
> 
> $ make all
> i686-unknown-linux-gnu-gcc -Wall -Wextra -O2 -fomit-frame-pointer -pipe
>  -fno-strict-aliasing -Wall -Wstrict-prototypes
>  -I/home/horms/local/opt/crosstool/i686/gcc-3.4.5-glibc-2.3.6/i686-unknown-
> linux-gnu/include -I./include -I./util_lib/include -Iinclude/
>  -I./kexec/arch/i386/include  -c -MD -o kexec/kexec.o kexec/kexec.c
> In file included from kexec/kexec.c:47:
> kexec/kexec-lzma.h:8:18: lzma.h: No such file or directory
> kexec/kexec.c: In function `locate_hole':
> kexec/kexec.c:203: warning: comparison between signed and unsigned
> 
> It ought to be possible to just provide a stub for zlib_decompress_file()
> in kexec-lzma.h and not compile lzma.c at all in the case where
> lzma support isn't being compiled in. However I see no obvious way
> to do this with the existing build system. So I'd like to deal
> with that as a separate possible change.
> 
> Changes as suggested by Eric W. Biederman.
> 
> Cc: Florian Fainelli <florian@openwrt.org>
> Cc: Eric W. Biederman <ebiederm@xmission.com>
> Signed-off-by: Simon Horman <horms@verge.net.au>
> 
> Index: kexec-tools/kexec/kexec-lzma.h
> ===================================================================
> --- kexec-tools.orig/kexec/kexec-lzma.h	2009-11-30 16:43:38.000000000 +1100
> +++ kexec-tools/kexec/kexec-lzma.h	2009-11-30 16:44:15.000000000 +1100
> @@ -1,29 +1,8 @@
>  #ifndef __KEXEC_LZMA_H
>  #define __KEXEC_LZMA_H
> 
> -#include <stdio.h>
>  #include <sys/types.h>
> -#include <unistd.h>
> -#include <inttypes.h>
> -#include <lzma.h>
> -
> -#include "config.h"
> -
> -#ifdef HAVE_LIBLZMA
> -#define kBufferSize (1 << 15)
> -
> -typedef struct lzfile {
> -	uint8_t buf[kBufferSize];
> -	lzma_stream strm;
> -	FILE *file;
> -	int encoding;
> -	int eof;
> -} LZFILE;
> -
> -LZFILE *lzopen(const char *path, const char *mode);
> -int lzclose(LZFILE *lzfile);
> -ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
> -#endif /* HAVE_LIBLZMA */
> 
>  char *lzma_decompress_file(const char *filename, off_t *r_size);
> +
>  #endif /* __KEXEC_LZMA_H */
> Index: kexec-tools/kexec/lzma.c
> ===================================================================
> --- kexec-tools.orig/kexec/lzma.c	2009-11-30 16:43:38.000000000 +1100
> +++ kexec-tools/kexec/lzma.c	2009-11-30 16:44:15.000000000 +1100
> @@ -1,4 +1,9 @@
> +#include <unistd.h>
> +#include <sys/types.h>
> +
>  #include "kexec-lzma.h"
> +#include "config.h"
> +
>  #ifdef HAVE_LIBLZMA
>  #define _GNU_SOURCE
>  #include <stdio.h>
> @@ -7,14 +12,26 @@
>  #include <stdlib.h>
>  #include <errno.h>
>  #include <limits.h>
> -#include <sys/types.h>
>  #include <sys/stat.h>
> -#include <unistd.h>
>  #include <ctype.h>
>  #include <lzma.h>
> 
>  #include "kexec.h"
> 
> +#define kBufferSize (1 << 15)
> +
> +typedef struct lzfile {
> +	uint8_t buf[kBufferSize];
> +	lzma_stream strm;
> +	FILE *file;
> +	int encoding;
> +	int eof;
> +} LZFILE;
> +
> +LZFILE *lzopen(const char *path, const char *mode);
> +int lzclose(LZFILE *lzfile);
> +ssize_t lzread(LZFILE *lzfile, void *buf, size_t len);
> +
>  static LZFILE *lzopen_internal(const char *path, const char *mode, int fd)
>  {
>  	int level = 5;
> 

-- 
WBR, Florian

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2009-11-30 10:09 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-11-15 23:53 [PATCH] add support for loading lzma compressed kernels Florian Fainelli
2009-11-16 13:37 ` wilbur.chan
2009-11-17  3:04 ` Simon Horman
2009-11-17 14:08   ` Florian Fainelli
2009-11-17 14:23     ` Florian Fainelli
2009-11-18  3:55       ` Simon Horman
2009-11-18 23:17         ` Florian Fainelli
2009-11-19  0:03           ` Eric W. Biederman
2009-11-30  5:51             ` Simon Horman
2009-11-30 10:08               ` Florian Fainelli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox