Subject: [PATCH] LZMA support for kernel images.

From: Luigi 'Comio' Mantellini <[email-masked]>
Date: Fri, 28 Mar 2008 18:00:39 +0100

Read lib_lzma/README.txt file first to enable the LZMA support.
---
 Makefile                   |    1 +
 common/cmd_bootm.c         |   23 ++++++++++++
 common/image.c             |    3 ++
 include/image.h            |    1 +
 include/lzma/LzmaDecode.h  |   31 ++++++++++++++++
 include/lzma/LzmaTools.h   |   31 ++++++++++++++++
 include/lzma/LzmaTypes.h   |   31 ++++++++++++++++
 lib_lzma/LzmaTools.c       |   87 ++++++++++++++++++++++++++++++++++++++++++++
 lib_lzma/LzmaTools.h       |   35 ++++++++++++++++++
 lib_lzma/Makefile          |   51 ++++++++++++++++++++++++++
 lib_lzma/README.txt        |   33 +++++++++++++++++
 lib_lzma/import_lzmasdk.sh |   38 +++++++++++++++++++
 12 files changed, 365 insertions(+), 0 deletions(-)
 create mode 100644 include/lzma/LzmaDecode.h
 create mode 100644 include/lzma/LzmaTools.h
 create mode 100644 include/lzma/LzmaTypes.h
 create mode 100644 lib_lzma/LzmaTools.c
 create mode 100644 lib_lzma/LzmaTools.h
 create mode 100644 lib_lzma/Makefile
 create mode 100644 lib_lzma/README.txt
 create mode 100644 lib_lzma/import_lzmasdk.sh

diff --git a/Makefile b/Makefile
index 4255cf5..03b16e2 100644
--- a/Makefile
+++ b/Makefile
@@ -192,6 +192,7 @@ endif
 OBJS := $(addprefix $(obj),$(OBJS))
 
 LIBS  = lib_generic/libgeneric.a
+LIBS += lib_lzma/lib_lzma.a
 LIBS += $(shell if [ -f board/$(VENDOR)/common/Makefile ]; then echo \
 	"board/$(VENDOR)/common/lib$(VENDOR).a"; fi)
 LIBS += board/$(BOARDDIR)/lib$(BOARD).a
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 9e5ce4b..ba6de50 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -40,6 +40,13 @@
 #include <hush.h>
 #endif
 
+#ifdef CONFIG_LZMA
+#define _7ZIP_BYTE_DEFINED /* Byte already defined by zlib */
+#include <lzma/LzmaTypes.h>
+#include <lzma/LzmaDecode.h>
+#include <lzma/LzmaTools.h>
+#endif /* CONFIG_LZMA */
+
 DECLARE_GLOBAL_DATA_PTR;
 
 extern int gunzip (void *dst, int dstlen, unsigned char *src, unsigned long *lenp);
@@ -271,6 +278,22 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 		load_end = load_start + unc_len;
 		break;
 #endif /* CONFIG_BZIP2 */
+#ifdef CONFIG_LZMA
+	case IH_COMP_LZMA:
+		printf ("   Uncompressing %s ... ", type_name);
+
+		int ret = lzmaBuffToBuffDecompress(
+			(unsigned char *)load_start, &unc_len,
+			(unsigned char *)os_data, os_len);
+		if (ret != LZMA_RESULT_OK) {
+			printf ("LZMA: uncompress or overwrite error %d "
+				"- must RESET board to recover\n", ret);
+			show_boot_progress (-6);
+			do_reset (cmdtp, flag, argc, argv);
+		}
+		load_end = load_start + unc_len;
+		break;
+#endif /* CONFIG_LZMA */
 	default:
 		if (iflag)
 			enable_interrupts();
diff --git a/common/image.c b/common/image.c
index f04826a..b1b036b 100644
--- a/common/image.c
+++ b/common/image.c
@@ -152,6 +152,9 @@ static table_entry_t uimage_comp[] = {
 	{	IH_COMP_NONE,	"none",		"uncompressed",		},
 	{	IH_COMP_BZIP2,	"bzip2",	"bzip2 compressed",	},
 	{	IH_COMP_GZIP,	"gzip",		"gzip compressed",	},
+#if defined(CONFIG_LZMA) || defined(USE_HOSTCC)
+	{	IH_COMP_LZMA,	"lzma",		"lzma compressed",	},
+#endif
 	{	-1,		"",		"",			},
 };
 
diff --git a/include/image.h b/include/image.h
index 36143e2..0126284 100644
--- a/include/image.h
+++ b/include/image.h
@@ -164,6 +164,7 @@
 #define IH_COMP_NONE		0	/*  No	 Compression Used	*/
 #define IH_COMP_GZIP		1	/* gzip	 Compression Used	*/
 #define IH_COMP_BZIP2		2	/* bzip2 Compression Used	*/
+#define IH_COMP_LZMA		3	/* lzma  Compression Used	*/
 
 #define IH_MAGIC	0x27051956	/* Image Magic Number		*/
 #define IH_NMLEN		32	/* Image Name Length		*/
diff --git a/include/lzma/LzmaDecode.h b/include/lzma/LzmaDecode.h
new file mode 100644
index 0000000..5e96fbf
--- /dev/null
+++ b/include/lzma/LzmaDecode.h
@@ -0,0 +1,31 @@
+/*
+ * Fake include for LzmaDecode.h
+ *
+ * Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini ([email-masked])
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+ 
+#ifndef __LZMADECODE_H__FAKE__
+#define __LZMADECODE_H__FAKE__
+
+#include "../../lib_lzma/LzmaDecode.h"
+
+#endif
diff --git a/include/lzma/LzmaTools.h b/include/lzma/LzmaTools.h
new file mode 100644
index 0000000..bf6df55
--- /dev/null
+++ b/include/lzma/LzmaTools.h
@@ -0,0 +1,31 @@
+/*
+ * Fake include for LzmaTools.h
+ *
+ * Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini ([email-masked])
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+ 
+#ifndef __LZMATOOLS_H__FAKE__
+#define __LZMATOOLS_H__FAKE__
+ 
+#include "../../lib_lzma/LzmaTools.h"
+ 
+#endif
diff --git a/include/lzma/LzmaTypes.h b/include/lzma/LzmaTypes.h
new file mode 100644
index 0000000..073d16e
--- /dev/null
+++ b/include/lzma/LzmaTypes.h
@@ -0,0 +1,31 @@
+/*
+ * Fake include for LzmaTypes.h
+ *
+ * Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini ([email-masked])
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+ 
+#ifndef __LZMATYPES_H__FAKE__
+#define __LZMATYPES_H__FAKE__
+ 
+#include "../../lib_lzma/LzmaTypes.h"
+ 
+#endif
diff --git a/lib_lzma/LzmaTools.c b/lib_lzma/LzmaTools.c
new file mode 100644
index 0000000..d024c46
--- /dev/null
+++ b/lib_lzma/LzmaTools.c
@@ -0,0 +1,87 @@
+/*
+ * Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.57
+ *
+ * Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini ([email-masked])
+ *
+ * Copyright (C) 1999-2005 Igor Pavlov
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "LzmaTools.h"
+#include "LzmaDecode.h"
+
+#include <linux/string.h>
+
+int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize,
+			      unsigned char *inStream,  SizeT  length)
+{
+	SizeT outSizeFull = 0xFFFFFFFF; /* 4GBytes limit */
+	SizeT inProcessed;
+	SizeT outProcessed;
+
+	CLzmaDecoderState state;  /* it's about 24-80 bytes structure, if int is 32-bit */
+	unsigned char properties[LZMA_PROPERTIES_SIZE];
+
+	SizeT compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8));
+	
+	memcpy(properties, inStream, LZMA_PROPERTIES_SIZE);
+		
+	inStream += LZMA_PROPERTIES_SIZE;
+	
+	int res;
+
+	/* Read LZMA properties for compressed stream */
+
+
+	/* Decode LZMA properties and allocate memory */
+  
+  	memset(&state, 0, sizeof(state));
+  	
+	res = LzmaDecodeProperties(&state.Properties,
+				 properties,
+				 LZMA_PROPERTIES_SIZE);
+	if (res != LZMA_RESULT_OK) {
+		return res;
+	}
+
+	state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
+
+	if (state.Probs == 0
+	    || (outStream == 0 && outSizeFull != 0)
+	    || (inStream == 0 && compressedSize != 0)) {
+		free(state.Probs);
+		return LZMA_RESULT_DATA_ERROR;
+	}
+
+	/* Decompress */
+
+	res = LzmaDecode(&state,
+		inStream, compressedSize, &inProcessed,
+		outStream, outSizeFull,  &outProcessed);
+	if (res != LZMA_RESULT_OK)  {
+		return res;
+	}
+
+	*uncompressedSize = outProcessed;
+	free(state.Probs);
+	return res;
+}
+
diff --git a/lib_lzma/LzmaTools.h b/lib_lzma/LzmaTools.h
new file mode 100644
index 0000000..ea51eef
--- /dev/null
+++ b/lib_lzma/LzmaTools.h
@@ -0,0 +1,35 @@
+/*
+ * Usefuls routines based on the LzmaTest.c file from LZMA SDK 4.57
+ *
+ * Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+ * Luigi 'Comio' Mantellini ([email-masked])
+ *
+ * Copyright (C) 1999-2005 Igor Pavlov
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+ 
+#ifndef __LZMA_TOOL_H__
+#define __LZMA_TOOL_H__
+
+#include "LzmaTypes.h"
+
+extern int lzmaBuffToBuffDecompress (unsigned char *outStream, SizeT *uncompressedSize,
+			      unsigned char *inStream,  SizeT  length);
+#endif
diff --git a/lib_lzma/Makefile b/lib_lzma/Makefile
new file mode 100644
index 0000000..e314241
--- /dev/null
+++ b/lib_lzma/Makefile
@@ -0,0 +1,51 @@
+#
+# Copyright (C) 2007-2008 Industrie Dial Face S.p.A.
+# Luigi 'Comio' Mantellini ([email-masked])
+#
+# (C) Copyright 2003-2006
+# Wolfgang Denk, DENX Software Engineering, [email-masked].
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)lib_lzma.a
+
+SOBJS	=
+
+COBJS-y +=	LzmaDecode.o \
+		LzmaTools.o
+
+COBJS	= $(COBJS-y)
+SRCS 	:= $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(SOBJS) $(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
+
diff --git a/lib_lzma/README.txt b/lib_lzma/README.txt
new file mode 100644
index 0000000..d070245
--- /dev/null
+++ b/lib_lzma/README.txt
@@ -0,0 +1,33 @@
+The lib_lzma functionality was written by Igor Pavlov. 
+The original source came from the LZMA SDK web page:
+
+URL: 		http://www.7-zip.org/sdk.html
+Author:         Igor Pavlov
+
+The import is made using the import_lzmasdk.sh script that:
+
+* untars the lzmaXYY.tar.bz2 file (from the download web page)
+* copies the files LzmaDecode.h, LzmaTypes.h, LzmaDecode.c, history.txt,
+  LGPL.txt, and lzma.txt from source archive into the lib_lzma directory (pwd).
+
+Example:
+
+ ./import_lzmasdk.sh ~/lzma457.tar.bz2
+
+Notice: The files from lzma sdk are not _modified_ by this script!
+
+The files LzmaTools.{c,h} are provided to export the lzmaBuffToBuffDecompress()
+function that wraps the complex LzmaDecode() function from the LZMA SDK. The
+do_bootm() function uses the lzmaBuffToBuffDecopress() function to expand the
+compressed image.
+
+The directory U-BOOT/include/lzma contains stubs files that permit to use the
+library directly from U-BOOT code without touching the original LZMA SDK's
+files.
+
+Finally, to enable the LZMA support you need to define into your board setup
+file.
+
+#define CONFIG_LZMA
+
+Luigi 'Comio' Mantellini <[email-masked]>
diff --git a/lib_lzma/import_lzmasdk.sh b/lib_lzma/import_lzmasdk.sh
new file mode 100644
index 0000000..3b4e232
--- /dev/null
+++ b/lib_lzma/import_lzmasdk.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+usage() {
+	echo "Usage: $0 lzmaVERSION.tar.bz2" >&2
+	echo >&2
+	exit 1
+}
+
+if [ "$1" = "" ] ; then
+ 	 usage
+fi
+
+if [ ! -f $1 ] ; then
+	echo "$1 doesn't exist!" >&2
+	exit 1
+fi
+
+BASENAME=`basename $1 .tar.bz2`
+TMPDIR=/tmp/tmp_lib_$BASENAME
+FILES="C/Compress/Lzma/LzmaDecode.h
+      C/Compress/Lzma/LzmaTypes.h  
+      C/Compress/Lzma/LzmaDecode.c 
+      history.txt                  
+      LGPL.txt                     
+      lzma.txt"
+
+
+mkdir -p $TMPDIR
+echo "Untar $1 -> $TMPDIR"
+tar -jxf $1 -C $TMPDIR
+
+for i in $FILES; do
+	echo Copying  $TMPDIR/$i \-\> `basename $i`
+	cp $TMPDIR/$i .
+	chmod -x `basename $i`
+done
+
+echo "done!"
-- 
1.5.4.3