diff -Nur linux-2.6.17.6/fs/Kconfig linux-2.6.17.6-bcm_squashfs/fs/Kconfig
--- linux-2.6.17.6/fs/Kconfig	2006-07-15 21:00:43.000000000 +0200
+++ linux-2.6.17.6-bcm_squashfs/fs/Kconfig	2006-09-26 12:41:07.000000000 +0200
@@ -1171,7 +1171,7 @@
 
 config CRAMFS
 	tristate "Compressed ROM file system support (cramfs)"
-	select ZLIB_INFLATE
+#	select ZLIB_INFLATE
 	help
 	  Saying Y here includes support for CramFs (Compressed ROM File
 	  System).  CramFs is designed to be a simple, small, and compressed
@@ -1188,6 +1188,44 @@
 
 	  If unsure, say N.
 
+config SQUASHFS
+	tristate "SquashFS 2.0 - Squashed file system support"
+#	select ZLIB_INFLATE
+	help
+	  Saying Y here includes support for SquashFs 2.0 (Compressed Read-Only File
+	  System).  Squashfs is a highly compressed read-only filesystem for Linux.
+	  It uses zlib compression to compress both files, inodes and directories.
+	  Inodes in the system are very small and all blocks are packed to minimise
+	  data overhead. Block sizes greater than 4K are supported up to a maximum of 64K.
+
+	  Squashfs is intended for general read-only filesystem use, for archival
+	  use (i.e. in cases where a .tar.gz file may be used), and in embedded
+	  systems where low overhead is needed.  Further information and filesystem tools
+	  are available from http://squashfs.sourceforge.net.
+
+	  If you want to compile this as a module ( = code which can be
+	  inserted in and removed from the running kernel whenever you want),
+	  say M here and read <file:Documentation/modules.txt>.  The module
+	  will be called squashfs.  Note that the root file system (the one
+	  containing the directory /) cannot be compiled as a module.
+
+	  If unsure, say N.
+
+choice
+	prompt "Decompression method"
+	depends on SQUASHFS || CRAMFS
+	default LZMA_FS_INFLATE
+
+config LZMA_FS_INFLATE
+	bool "LZMA"
+
+config ZLIB_FS_INFLATE
+	bool "ZLIB"
+	select ZLIB_INFLATE
+
+endchoice
+
+
 config VXFS_FS
 	tristate "FreeVxFS file system support (VERITAS VxFS(TM) compatible)"
 	help
diff -Nur linux-2.6.17.6/fs/Makefile linux-2.6.17.6-bcm_squashfs/fs/Makefile
--- linux-2.6.17.6/fs/Makefile	2006-07-15 21:00:43.000000000 +0200
+++ linux-2.6.17.6-bcm_squashfs/fs/Makefile	2006-09-16 09:52:49.000000000 +0200
@@ -56,6 +56,7 @@
 obj-$(CONFIG_JBD)		+= jbd/
 obj-$(CONFIG_EXT2_FS)		+= ext2/
 obj-$(CONFIG_CRAMFS)		+= cramfs/
+obj-$(CONFIG_SQUASHFS)		+= squashfs/
 obj-$(CONFIG_RAMFS)		+= ramfs/
 obj-$(CONFIG_HUGETLBFS)		+= hugetlbfs/
 obj-$(CONFIG_CODA_FS)		+= coda/
diff -Nur linux-2.6.17.6/fs/inflate_lzma/7z.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/7z.h
--- linux-2.6.17.6/fs/inflate_lzma/7z.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/7z.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,16 @@
+#ifndef __7Z_H
+#define __7Z_H
+
+#if defined __cplusplus
+extern "C"
+{
+#endif
+
+int decompress_lzma_7z(unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size);
+
+#if defined __cplusplus
+}
+#endif
+
+#endif
+
diff -Nur linux-2.6.17.6/fs/inflate_lzma/7zlzma.c linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/7zlzma.c
--- linux-2.6.17.6/fs/inflate_lzma/7zlzma.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/7zlzma.c	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,57 @@
+#include "7z.h"
+
+#ifdef _HOST_TOOL
+#include "stdio.h"
+#endif
+
+#include "LZMADecoder.h"
+
+
+static LzmaDecoder   cc;
+ISequentialInStream  in_stream;
+ISequentialOutStream out_stream;
+int decompress_lzma_7z( unsigned char* in_data, 
+                        unsigned in_size, 
+                        unsigned char* out_data, 
+                        unsigned out_size) {
+//		LzmaDecoder cc;
+        int RC;
+	UINT64 in_size_l  = in_size;
+	UINT64 out_size_l = out_size;
+
+
+        InStreamInit(in_data, in_size);
+
+	OutStreamInit((char *)out_data, out_size);
+
+        LzmaDecoderConstructor(&cc);
+
+        if ((RC = LzmaDecoderReadCoderProperties(&cc)) != S_OK)
+        {
+		return RC;
+        }
+
+	if (LzmaDecoderCode(&cc, &in_size_l, &out_size_l) != S_OK)
+        {
+		return -2;
+        }
+
+	if (out_stream.size != out_size)
+        {
+		return -3;
+        }
+
+        if ( out_stream.overflow )
+        {
+            return -4;
+        }
+
+	return 0;
+}
+
+//BRCM modification
+#ifdef __KERNEL__
+EXPORT_SYMBOL(decompress_lzma_7z);
+#endif
+
+
diff -Nur linux-2.6.17.6/fs/inflate_lzma/AriBitCoder.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/AriBitCoder.h
--- linux-2.6.17.6/fs/inflate_lzma/AriBitCoder.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/AriBitCoder.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,51 @@
+#ifndef __COMPRESSION_BITCODER_H
+#define __COMPRESSION_BITCODER_H
+
+#include "RangeCoder.h"
+
+#define kNumBitModelTotalBits  11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+
+#define kNumMoveReducingBits 2
+
+
+typedef UINT32 CBitDecoder;
+
+INLINE  void BitDecoderInit(CBitDecoder *bitDecoder)
+  { 
+    *bitDecoder = kBitModelTotal / 2; 
+  }
+
+#if 0
+UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder);
+#else
+INLINE  UINT32 BitDecode(ISequentialInStream *in_stream, CBitDecoder *bitDecoder, CRangeDecoder *aRangeDecoder)
+  {
+    UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * (*bitDecoder);
+    if (aRangeDecoder->m_Code < aNewBound)
+    {
+      aRangeDecoder->m_Range = aNewBound;
+      *bitDecoder += (kBitModelTotal - *bitDecoder) >> kNumMoveBits;
+      if (aRangeDecoder->m_Range < kTopValue)
+      {
+        aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream);
+        aRangeDecoder->m_Range <<= 8;
+      }
+      return 0;
+    }
+    else
+    {
+      aRangeDecoder->m_Range -= aNewBound;
+      aRangeDecoder->m_Code -= aNewBound;
+      *bitDecoder -= (*bitDecoder) >> kNumMoveBits;
+      if (aRangeDecoder->m_Range < kTopValue)
+      {
+        aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | InStreamReadByte(in_stream);
+        aRangeDecoder->m_Range <<= 8;
+      }
+      return 1;
+    }
+  }
+#endif
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/BitTreeCoder.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/BitTreeCoder.h
--- linux-2.6.17.6/fs/inflate_lzma/BitTreeCoder.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/BitTreeCoder.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,160 @@
+#ifndef __BITTREECODER_H
+#define __BITTREECODER_H
+
+#include "AriBitCoder.h"
+#include "RCDefs.h"
+
+//BRCM modification start
+#ifdef _HOST_TOOL
+#include "stdio.h"
+#include "stdlib.h"
+#include "malloc.h" 
+#endif
+
+#ifdef _CFE_
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#define malloc(x) KMALLOC(x, 0)
+#endif
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#define printf printk
+//#define malloc(x) kmalloc(x,GFP_KERNEL)
+#define malloc(x) vmalloc(x)
+#define free(x) vfree(x)
+#endif
+//BRCM modification end
+
+//////////////////////////
+// CBitTreeDecoder
+
+typedef struct CBitTreeDecoder
+{
+  UINT32       m_NumBitLevels;
+  CBitDecoder *m_Models;
+} CBitTreeDecoder;
+
+//  ~CBitTreeDecoder() { free(m_Models); }
+INLINE void BitTreeDecoderInit(CBitTreeDecoder *bitTreeDecoder, UINT32 aNumBitLevels)
+  {
+    int i;
+    bitTreeDecoder->m_NumBitLevels = aNumBitLevels;
+    bitTreeDecoder->m_Models       = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels));
+    //BRCM modification
+    //printf("malloc in BitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << bitTreeDecoder->m_NumBitLevels));
+    if (!bitTreeDecoder->m_Models) {
+	    printf("Error in allocating memory for bitTreeDecoder!\n");
+	    return;
+    }	    
+    for(i = 1; i < (1 << aNumBitLevels); i++)
+      BitDecoderInit(&bitTreeDecoder->m_Models[i]);
+  }
+INLINE UINT32 BitTreeDecode(ISequentialInStream *in_stream, CBitTreeDecoder *bitTreeDecoder, CRangeDecoder *aRangeDecoder)
+  {
+    UINT32 aModelIndex = 1;
+    UINT32 aRange = aRangeDecoder->m_Range;
+    UINT32 aCode = aRangeDecoder->m_Code;
+    UINT32 aBitIndex;
+    for(aBitIndex = bitTreeDecoder->m_NumBitLevels; aBitIndex > 0; aBitIndex--)
+    {
+      RC_GETBIT(kNumMoveBits, bitTreeDecoder->m_Models[aModelIndex], aModelIndex)
+    }
+    aRangeDecoder->m_Range = aRange;
+    aRangeDecoder->m_Code = aCode;
+    return aModelIndex - (1 << bitTreeDecoder->m_NumBitLevels);
+  }
+
+
+////////////////////////////////
+// CReverseBitTreeDecoder2
+
+typedef struct CReverseBitTreeDecoder2
+{
+  UINT32       m_NumBitLevels;
+  CBitDecoder *m_Models;
+} CReverseBitTreeDecoder2;
+
+//  CReverseBitTreeDecoder2(): m_Models(0) { }
+//  ~CReverseBitTreeDecoder2() { free(m_Models); }
+INLINE BOOL ReverseBitTreeDecoder2Create(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, UINT32 aNumBitLevels)
+  {
+    reverseBitTreeDecoder2->m_NumBitLevels = aNumBitLevels;
+    reverseBitTreeDecoder2->m_Models       = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels));
+    //printf("malloc in ReverseBitTreeDecoder2Create=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder2->m_NumBitLevels));
+    if (!reverseBitTreeDecoder2->m_Models) {
+	    printf("Error in allocating memory for reverseBitTreeDecoder2!\n");
+	    return 0;
+    }	    
+    return (reverseBitTreeDecoder2->m_Models != 0);
+  }
+INLINE void ReverseBitTreeDecoder2Init(CReverseBitTreeDecoder2 *reverseBitTreeDecoder2)
+  {
+    UINT32 aNumModels = 1 << reverseBitTreeDecoder2->m_NumBitLevels;
+    UINT32 i;
+    for(i = 1; i < aNumModels; i++)
+      BitDecoderInit(&reverseBitTreeDecoder2->m_Models[i]);
+  }
+INLINE UINT32 ReverseBitTreeDecoder2Decode(ISequentialInStream *in_stream, CReverseBitTreeDecoder2 *reverseBitTreeDecoder2, CRangeDecoder *aRangeDecoder)
+  {
+    UINT32 aModelIndex = 1;
+    UINT32 aSymbol = 0;
+    UINT32 aRange = aRangeDecoder->m_Range;
+    UINT32 aCode = aRangeDecoder->m_Code;
+    UINT32 aBitIndex;
+    for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder2->m_NumBitLevels; aBitIndex++)
+    {
+      RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder2->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex))
+    }
+    aRangeDecoder->m_Range = aRange;
+    aRangeDecoder->m_Code = aCode;
+    return aSymbol;
+  }
+
+
+////////////////////////////
+// CReverseBitTreeDecoder
+
+typedef struct CReverseBitTreeDecoder
+{
+  UINT32        m_NumBitLevels;
+  CBitDecoder  *m_Models;
+} CReverseBitTreeDecoder;
+
+//    CReverseBitTreeDecoder(): m_Models(0) { }
+//    ~CReverseBitTreeDecoder() { free(m_Models); }
+INLINE void ReverseBitTreeDecoderInit(CReverseBitTreeDecoder *reverseBitTreeDecoder, UINT32 aNumBitLevels)
+  {
+    int i;
+    reverseBitTreeDecoder->m_NumBitLevels = aNumBitLevels;
+    reverseBitTreeDecoder->m_Models       = (CBitDecoder *)malloc( sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels));
+    //printf("malloc in ReverseBitTreeDecoderInit=%d\n",sizeof(CBitDecoder) * (1 << reverseBitTreeDecoder->m_NumBitLevels));
+    if (!reverseBitTreeDecoder->m_Models) {
+	    printf("Error in allocating memory for reverseBitTreeDecoder!\n");
+	    return;
+    }	    
+    for(i = 1; i < (1 << reverseBitTreeDecoder->m_NumBitLevels); i++)
+      BitDecoderInit(&reverseBitTreeDecoder->m_Models[i]);
+  }
+
+INLINE UINT32 ReverseBitTreeDecoderDecode(ISequentialInStream *in_stream, CReverseBitTreeDecoder *reverseBitTreeDecoder, CRangeDecoder *aRangeDecoder)
+  {
+    UINT32 aModelIndex = 1;
+    UINT32 aSymbol = 0;
+    UINT32 aRange = aRangeDecoder->m_Range;
+    UINT32 aCode = aRangeDecoder->m_Code;
+    UINT32 aBitIndex;
+    for(aBitIndex = 0; aBitIndex < reverseBitTreeDecoder->m_NumBitLevels; aBitIndex++)
+    {
+      RC_GETBIT2(kNumMoveBits, reverseBitTreeDecoder->m_Models[aModelIndex], aModelIndex, ; , aSymbol |= (1 << aBitIndex))
+    }
+    aRangeDecoder->m_Range = aRange;
+    aRangeDecoder->m_Code = aCode;
+    return aSymbol;
+  }
+
+
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/IInOutStreams.c linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/IInOutStreams.c
--- linux-2.6.17.6/fs/inflate_lzma/IInOutStreams.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/IInOutStreams.c	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,38 @@
+#include "IInOutStreams.h"
+// BRCM modification 
+static void *lib_memcpy(void *dest,const void *src,size_t cnt);
+static void *lib_memcpy(void *dest,const void *src,size_t cnt)
+{
+    unsigned char *d;
+    const unsigned char *s;
+
+    d = (unsigned char *) dest;
+    s = (const unsigned char *) src;
+
+    while (cnt) {
+	*d++ = *s++;
+	cnt--;
+	}
+
+    return dest;
+}
+
+HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize) {
+    	if (aSize > in_stream.remainingBytes)
+    		aSize = in_stream.remainingBytes;
+    	*aProcessedSize = aSize;
+    	lib_memcpy(aData, in_stream.data, aSize); // brcm modification
+    	in_stream.remainingBytes -= aSize;
+    	in_stream.data += aSize;
+    	return S_OK;
+    }
+
+#if 0
+BYTE InStreamReadByte()
+    {
+        if (in_stream.remainingBytes == 0)
+            return 0x0;
+        in_stream.remainingBytes--;
+        return (BYTE) *in_stream.data++;
+    }
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/IInOutStreams.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/IInOutStreams.h
--- linux-2.6.17.6/fs/inflate_lzma/IInOutStreams.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/IInOutStreams.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,62 @@
+#ifndef __IINOUTSTREAMS_H
+#define __IINOUTSTREAMS_H
+
+#include "Portable.h"
+
+typedef struct ISequentialInStream
+{
+	unsigned char* data;
+	unsigned       remainingBytes;
+} ISequentialInStream;
+
+extern ISequentialInStream in_stream;
+
+INLINE void InStreamInit(unsigned char * Adata, unsigned Asize)
+    {
+        in_stream.data           = Adata;
+        in_stream.remainingBytes = Asize;
+    }
+
+HRESULT InStreamRead(void *aData, UINT32 aSize, UINT32* aProcessedSize);
+
+#if 0
+BYTE InStreamReadByte();
+#else
+INLINE BYTE InStreamReadByte(ISequentialInStream *in_stream)
+    {
+        if (in_stream->remainingBytes == 0)
+            return 0x0;
+        in_stream->remainingBytes--;
+        return (BYTE) *in_stream->data++;
+    }
+#endif
+
+
+
+typedef struct ISequentialOutStream
+{
+	char*       data;
+	unsigned    size;
+	BOOL        overflow;
+	unsigned    total;
+} ISequentialOutStream;
+
+extern ISequentialOutStream out_stream;
+
+#define OutStreamInit(Adata, Asize) \
+{ \
+    out_stream.data = Adata; \
+    out_stream.size = Asize; \
+    out_stream.overflow = FALSE; \
+    out_stream.total = 0; \
+}
+
+#define OutStreamSizeSet(newsize) \
+    { \
+        out_stream.total = newsize; \
+        if (out_stream.total > out_stream.size) \
+            out_stream.overflow = TRUE; \
+    }
+
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/LZMA.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LZMA.h
--- linux-2.6.17.6/fs/inflate_lzma/LZMA.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LZMA.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,83 @@
+#include "LenCoder.h"
+
+#ifndef __LZMA_H
+#define __LZMA_H
+
+
+#define kNumRepDistances 4
+
+#define kNumStates 12
+
+static const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
+static const BYTE kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+static const BYTE kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+static const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+typedef BYTE CState;
+
+INLINE void CStateInit(CState *m_Index)
+    { *m_Index = 0; }
+INLINE void CStateUpdateChar(CState *m_Index)
+    { *m_Index = kLiteralNextStates[*m_Index]; }
+INLINE void CStateUpdateMatch(CState *m_Index)
+    { *m_Index = kMatchNextStates[*m_Index]; }
+INLINE void CStateUpdateRep(CState *m_Index)
+    { *m_Index = kRepNextStates[*m_Index]; }
+INLINE void CStateUpdateShortRep(CState *m_Index)
+    { *m_Index = kShortRepNextStates[*m_Index]; }
+
+
+#define kNumPosSlotBits 6
+#define kDicLogSizeMax 28
+#define kDistTableSizeMax 56
+
+//extern UINT32 kDistStart[kDistTableSizeMax];
+static const BYTE kDistDirectBits[kDistTableSizeMax] = 
+{
+  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+  10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 
+  20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 
+};
+
+#define kNumLenToPosStates 4
+INLINE UINT32 GetLenToPosState(UINT32 aLen)
+{
+  aLen -= 2;
+  if (aLen < kNumLenToPosStates)
+    return aLen;
+  return kNumLenToPosStates - 1;
+}
+
+#define kMatchMinLen 2
+
+#define kMatchMaxLen (kMatchMinLen + kNumSymbolsTotal - 1)
+
+#define kNumAlignBits 4
+#define kAlignTableSize 16
+#define kAlignMask 15
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumPosModels 10
+
+#define kNumFullDistances (1 << (kEndPosModelIndex / 2))
+
+
+#define kMainChoiceLiteralIndex 0
+#define kMainChoiceMatchIndex 1
+
+#define kMatchChoiceDistanceIndex0
+#define kMatchChoiceRepetitionIndex 1
+
+#define kNumMoveBitsForMainChoice 5
+#define kNumMoveBitsForPosCoders 5
+
+#define kNumMoveBitsForAlignCoders 5
+
+#define kNumMoveBitsForPosSlotCoder 5
+
+#define kNumLitPosStatesBitsEncodingMax 4
+#define kNumLitContextBitsMax 8
+
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/LZMADecoder.c linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LZMADecoder.c
--- linux-2.6.17.6/fs/inflate_lzma/LZMADecoder.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LZMADecoder.c	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,398 @@
+#include "Portable.h"
+#ifdef _HOST_TOOL
+#include "stdio.h"
+#endif
+#include "LZMADecoder.h"
+
+
+//#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; }
+
+
+static UINT32    kDistStart[kDistTableSizeMax];
+struct WindowOut out_window;
+
+/*
+ * BRCM modification: free all the allocated buffer by malloc
+ *
+ */
+static void LzmaDecoderFreeBuffer(LzmaDecoder  *lzmaDecoder)
+{
+  int i,aPosState;
+  
+  //printf("free lzmaDecoder->m_LiteralDecoder\n");
+  free((&lzmaDecoder->m_LiteralDecoder)->m_Coders);
+
+  for (i = 0; i < kNumLenToPosStates; i++) {
+      //printf("free lzmaDecoder->m_PosSlotDecoder\n");
+      free((&lzmaDecoder->m_PosSlotDecoder[i])->m_Models);
+  }
+  // from LenDecoderInit(&lzmaDecoder->m_LenDecoder;
+  for (aPosState = 0; aPosState < (&lzmaDecoder->m_LenDecoder)->m_NumPosStates; aPosState++) {
+      //printf("free lzmaDecoder->m_PosSlotDecoder\n");
+      free( (&(&lzmaDecoder->m_LenDecoder)->m_LowCoder[aPosState])->m_Models );
+      //printf("free lzmaDecoder->m_PosSlotDecoder\n");
+      free( (&(&lzmaDecoder->m_LenDecoder)->m_MidCoder[aPosState])->m_Models );
+   }
+  //printf("free lzmaDecoder->m_PosSlotDecoder\n");
+  free( (&(&lzmaDecoder->m_LenDecoder)->m_HighCoder)->m_Models );
+
+
+  // from LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder);
+  for (aPosState = 0; aPosState < (&lzmaDecoder->m_RepMatchLenDecoder)->m_NumPosStates; aPosState++) {
+      //printf("free lzmaDecoder->m_PosSlotDecoder\n");
+      free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_LowCoder[aPosState])->m_Models );
+      //printf("free lzmaDecoder->m_PosSlotDecoder\n");
+      free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_MidCoder[aPosState])->m_Models );
+  }
+  //printf("free lzmaDecoder->m_PosSlotDecoder\n");
+  free( (&(&lzmaDecoder->m_RepMatchLenDecoder)->m_HighCoder)->m_Models );
+
+    
+  //printf("free lzmaDecoder->m_PosAlignDecoder\n");
+  free((&lzmaDecoder->m_PosAlignDecoder)->m_Models);
+
+  for(i = 0; i < kNumPosModels; i++) {
+      //printf("free lzmaDecoder->m_PosDecoders\n");
+      free((&lzmaDecoder->m_PosDecoders[i])->m_Models);
+  }
+  
+}
+
+HRESULT LzmaDecoderSetDictionarySize(
+    LzmaDecoder  *lzmaDecoder, 
+    UINT32        aDictionarySize)
+{
+  if (aDictionarySize > (1 << kDicLogSizeMax))
+    return E_INVALIDARG;
+  
+//  UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21));
+
+  if (lzmaDecoder->m_DictionarySize != aDictionarySize)
+  {
+    lzmaDecoder->m_DictionarySize = aDictionarySize;
+  }
+  return S_OK;
+}
+
+HRESULT LzmaDecoderSetLiteralProperties( 
+    LzmaDecoder  *lzmaDecoder,
+    UINT32        aLiteralPosStateBits, 
+    UINT32        aLiteralContextBits)
+{
+  if (aLiteralPosStateBits > 8)
+    return E_INVALIDARG;
+  if (aLiteralContextBits > 8)
+    return E_INVALIDARG;
+  LitDecoderCreate(&lzmaDecoder->m_LiteralDecoder, aLiteralPosStateBits, aLiteralContextBits);
+  return S_OK;
+}
+
+HRESULT LzmaDecoderSetPosBitsProperties(
+    LzmaDecoder *lzmaDecoder, 
+    UINT32       aNumPosStateBits)
+{
+  UINT32 aNumPosStates;
+  if (aNumPosStateBits > (UINT32) kNumPosStatesBitsMax)
+    return E_INVALIDARG;
+  aNumPosStates = 1 << aNumPosStateBits;
+  LenDecoderCreate(&lzmaDecoder->m_LenDecoder, aNumPosStates);
+  LenDecoderCreate(&lzmaDecoder->m_RepMatchLenDecoder, aNumPosStates);
+  lzmaDecoder->m_PosStateMask = aNumPosStates - 1;
+  return S_OK;
+}
+
+
+void LzmaDecoderConstructor(LzmaDecoder *lzmaDecoder)
+{
+  lzmaDecoder->m_DictionarySize = ((UINT32)-1);
+  LzmaDecoderCreate(lzmaDecoder);
+}
+
+HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder)
+{
+  int i;
+  for(i = 0; i < kNumPosModels; i++)
+  {
+    if (!(ReverseBitTreeDecoder2Create(&lzmaDecoder->m_PosDecoders[i],kDistDirectBits[kStartPosModelIndex + i])))
+        return E_OUTOFMEMORY;;
+  }
+  return S_OK;
+}
+
+
+HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder)
+{
+  int    i;
+  UINT32 j;
+
+  RangeDecoderInit(&in_stream, &lzmaDecoder->m_RangeDecoder);
+
+  OutWindowInit();
+
+  for(i = 0; i < kNumStates; i++)
+  {
+    for (j = 0; j <= lzmaDecoder->m_PosStateMask; j++)
+    {
+      BitDecoderInit(&lzmaDecoder->m_MainChoiceDecoders[i][j]);
+      BitDecoderInit(&lzmaDecoder->m_MatchRepShortChoiceDecoders[i][j]);
+    }
+    BitDecoderInit(&lzmaDecoder->m_MatchChoiceDecoders[i]);
+    BitDecoderInit(&lzmaDecoder->m_MatchRepChoiceDecoders[i]);
+    BitDecoderInit(&lzmaDecoder->m_MatchRep1ChoiceDecoders[i]);
+    BitDecoderInit(&lzmaDecoder->m_MatchRep2ChoiceDecoders[i]);
+  }
+  
+  LitDecoderInit(&lzmaDecoder->m_LiteralDecoder);
+   
+  for (i = 0; i < (int) kNumLenToPosStates; i++)
+    BitTreeDecoderInit(&lzmaDecoder->m_PosSlotDecoder[i],kNumPosSlotBits);
+
+  for(i = 0; i < kNumPosModels; i++)
+    ReverseBitTreeDecoder2Init(&lzmaDecoder->m_PosDecoders[i]);
+  
+  LenDecoderInit(&lzmaDecoder->m_LenDecoder);
+  LenDecoderInit(&lzmaDecoder->m_RepMatchLenDecoder);
+
+  ReverseBitTreeDecoderInit(&lzmaDecoder->m_PosAlignDecoder, kNumAlignBits);
+  return S_OK;
+
+}
+
+HRESULT LzmaDecoderCodeReal( 
+    LzmaDecoder     *lzmaDecoder, 
+    UINT64          *anInSize, 
+    UINT64          *anOutSize)
+{
+  BOOL                  aPeviousIsMatch         = FALSE;
+  BYTE                  aPreviousByte           = 0;
+  UINT32                aRepDistances[kNumRepDistances];
+  int                   i;
+  UINT64                aNowPos64               = 0;
+  UINT64                aSize                   = *anOutSize;
+  ISequentialInStream   my_in_stream;
+//  WindowOut             out_window;
+  CState                aState;
+
+  CStateInit(&aState);
+
+  if (anOutSize == NULL)
+  {
+      printf("CodeReal: invalid argument %x\n", (UINT32) anOutSize );
+      return E_INVALIDARG;
+  }
+
+
+  LzmaDecoderInit(lzmaDecoder);
+
+  my_in_stream.data           = in_stream.data;
+  my_in_stream.remainingBytes = in_stream.remainingBytes;
+
+  for(i = 0 ; i < (int) kNumRepDistances; i++)
+    aRepDistances[i] = 0;
+
+  //while(aNowPos64 < aSize)
+  while(my_in_stream.remainingBytes > 0)
+  {
+    UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize);
+    while(aNowPos64 < aNext)
+    {
+      UINT32 aPosState = (UINT32)(aNowPos64) & lzmaDecoder->m_PosStateMask;
+      if (BitDecode(&my_in_stream, 
+                    &lzmaDecoder->m_MainChoiceDecoders[aState][aPosState], 
+                    &lzmaDecoder->m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex)
+      {
+        CStateUpdateChar(&aState);
+        if(aPeviousIsMatch)
+        {
+          BYTE aMatchByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1);
+          aPreviousByte = LitDecodeWithMatchByte(&my_in_stream, 
+                                                 &lzmaDecoder->m_LiteralDecoder, 
+                                                 &lzmaDecoder->m_RangeDecoder, 
+                                                 (UINT32)(aNowPos64), 
+                                                 aPreviousByte, 
+                                                 aMatchByte);
+          aPeviousIsMatch = FALSE;
+        }
+        else
+          aPreviousByte = LitDecodeNormal(&my_in_stream, 
+                                          &lzmaDecoder->m_LiteralDecoder, 
+                                          &lzmaDecoder->m_RangeDecoder, 
+                                         (UINT32)(aNowPos64), 
+                                          aPreviousByte);
+        OutWindowPutOneByte(aPreviousByte);
+        aNowPos64++;
+      }
+      else             
+      {
+        UINT32 aDistance, aLen;
+        aPeviousIsMatch = TRUE;
+        if(BitDecode(&my_in_stream, 
+                     &lzmaDecoder->m_MatchChoiceDecoders[aState], 
+                     &lzmaDecoder->m_RangeDecoder) == (UINT32) kMatchChoiceRepetitionIndex)
+        {
+          if(BitDecode(&my_in_stream, 
+                       &lzmaDecoder->m_MatchRepChoiceDecoders[aState], 
+                       &lzmaDecoder->m_RangeDecoder) == 0)
+          {
+            if(BitDecode(&my_in_stream, 
+                         &lzmaDecoder->m_MatchRepShortChoiceDecoders[aState][aPosState], 
+                         &lzmaDecoder->m_RangeDecoder) == 0)
+            {
+              CStateUpdateShortRep(&aState);
+              aPreviousByte = OutWindowGetOneByte(0 - aRepDistances[0] - 1);
+              OutWindowPutOneByte(aPreviousByte);
+              aNowPos64++;
+              continue;
+            }
+            aDistance = aRepDistances[0];
+          }
+          else
+          {
+            if(BitDecode(&my_in_stream, 
+                         &lzmaDecoder->m_MatchRep1ChoiceDecoders[aState], 
+                         &lzmaDecoder->m_RangeDecoder) == 0)
+            {
+              aDistance = aRepDistances[1];
+              aRepDistances[1] = aRepDistances[0];
+            }
+            else 
+            {
+              if (BitDecode(&my_in_stream, 
+                            &lzmaDecoder->m_MatchRep2ChoiceDecoders[aState], 
+                            &lzmaDecoder->m_RangeDecoder) == 0)
+              {
+                aDistance = aRepDistances[2];
+              }
+              else
+              {
+                aDistance = aRepDistances[3];
+                aRepDistances[3] = aRepDistances[2];
+              }
+              aRepDistances[2] = aRepDistances[1];
+              aRepDistances[1] = aRepDistances[0];
+            }
+            aRepDistances[0] = aDistance;
+          }
+          aLen = LenDecode(&my_in_stream, 
+                           &lzmaDecoder->m_RepMatchLenDecoder, 
+                           &lzmaDecoder->m_RangeDecoder, 
+                           aPosState) + kMatchMinLen;
+          CStateUpdateRep(&aState);
+        }
+        else
+        {
+          UINT32 aPosSlot;
+          aLen = kMatchMinLen + LenDecode(&my_in_stream, 
+                                          &lzmaDecoder->m_LenDecoder, 
+                                          &lzmaDecoder->m_RangeDecoder, 
+                                          aPosState);
+          CStateUpdateMatch(&aState);
+          aPosSlot = BitTreeDecode(&my_in_stream, 
+                                   &lzmaDecoder->m_PosSlotDecoder[GetLenToPosState(aLen)],
+                                   &lzmaDecoder->m_RangeDecoder);
+          if (aPosSlot >= (UINT32) kStartPosModelIndex)
+          {
+            aDistance = kDistStart[aPosSlot];
+            if (aPosSlot < (UINT32) kEndPosModelIndex)
+              aDistance += ReverseBitTreeDecoder2Decode(&my_in_stream, 
+                                                        &lzmaDecoder->m_PosDecoders[aPosSlot - kStartPosModelIndex],
+                                                        &lzmaDecoder->m_RangeDecoder);
+            else
+            {
+              aDistance += (RangeDecodeDirectBits(&my_in_stream, 
+                                                  &lzmaDecoder->m_RangeDecoder, 
+                                                  kDistDirectBits[aPosSlot] - kNumAlignBits) << kNumAlignBits);
+              aDistance += ReverseBitTreeDecoderDecode(&my_in_stream, 
+                                                       &lzmaDecoder->m_PosAlignDecoder, 
+                                                       &lzmaDecoder->m_RangeDecoder);
+            }
+          }
+          else
+            aDistance = aPosSlot;
+
+          
+          aRepDistances[3] = aRepDistances[2];
+          aRepDistances[2] = aRepDistances[1];
+          aRepDistances[1] = aRepDistances[0];
+          
+          aRepDistances[0] = aDistance;
+        }
+        if (aDistance >= aNowPos64)
+        {
+            printf("CodeReal: invalid data\n" );
+            return E_INVALIDDATA;
+        }
+        OutWindowCopyBackBlock(aDistance, aLen);
+        aNowPos64 += aLen;
+        aPreviousByte = OutWindowGetOneByte(0 - 1);
+      }
+    }
+  }
+  
+  //BRCM modification
+  LzmaDecoderFreeBuffer(lzmaDecoder);
+  
+  OutWindowFlush();
+  return S_OK;
+}
+
+HRESULT LzmaDecoderCode(
+    LzmaDecoder *lzmaDecoder,
+    UINT64 *anInSize, 
+    UINT64 *anOutSize)
+{
+
+    UINT32 aStartValue = 0;
+    int i;
+    
+    for (i = 0; i < kDistTableSizeMax; i++)
+    {
+        kDistStart[i] = aStartValue;
+        aStartValue += (1 << kDistDirectBits[i]);
+    }
+    return LzmaDecoderCodeReal( 
+        lzmaDecoder, 
+        anInSize, 
+        anOutSize);
+}
+
+HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder)
+{
+  UINT32 aNumPosStateBits;
+  UINT32 aLiteralPosStateBits;
+  UINT32 aLiteralContextBits;
+  UINT32 aDictionarySize;
+  BYTE   aRemainder;
+  UINT32 aProcessesedSize;
+
+  BYTE aByte;
+  RETURN_IF_NOT_S_OK(InStreamRead(&aByte, 
+                                  sizeof(aByte), 
+                                  &aProcessesedSize));
+
+  if (aProcessesedSize != sizeof(aByte))
+    return E_INVALIDARG;
+
+  aLiteralContextBits   = aByte % 9;
+  aRemainder            = aByte / 9;
+  aLiteralPosStateBits  = aRemainder % 5;
+  aNumPosStateBits      = aRemainder / 5;
+
+  RETURN_IF_NOT_S_OK(InStreamRead(&aDictionarySize, 
+                                  sizeof(aDictionarySize), 
+                                  &aProcessesedSize));
+
+  if (aProcessesedSize != sizeof(aDictionarySize))
+    return E_INVALIDARG;
+
+  RETURN_IF_NOT_S_OK( LzmaDecoderSetDictionarySize(lzmaDecoder, 
+                                                   aDictionarySize) );
+  RETURN_IF_NOT_S_OK( LzmaDecoderSetLiteralProperties(lzmaDecoder, 
+                                                      aLiteralPosStateBits, 
+                                                      aLiteralContextBits) );
+  RETURN_IF_NOT_S_OK( LzmaDecoderSetPosBitsProperties(lzmaDecoder, 
+                                                      aNumPosStateBits) );
+
+  return S_OK;
+}
+
diff -Nur linux-2.6.17.6/fs/inflate_lzma/LZMADecoder.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LZMADecoder.h
--- linux-2.6.17.6/fs/inflate_lzma/LZMADecoder.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LZMADecoder.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,60 @@
+#ifndef __LZARITHMETIC_DECODER_H
+#define __LZARITHMETIC_DECODER_H
+
+#include "WindowOut.h"
+#include "LZMA.h"
+#include "LenCoder.h"
+#include "LiteralCoder.h"
+
+
+typedef struct LzmaDecoder
+{
+  CRangeDecoder m_RangeDecoder;
+
+  CBitDecoder m_MainChoiceDecoders[kNumStates][kNumPosStatesMax];
+  CBitDecoder m_MatchChoiceDecoders[kNumStates];
+  CBitDecoder m_MatchRepChoiceDecoders[kNumStates];
+  CBitDecoder m_MatchRep1ChoiceDecoders[kNumStates];
+  CBitDecoder m_MatchRep2ChoiceDecoders[kNumStates];
+  CBitDecoder m_MatchRepShortChoiceDecoders[kNumStates][kNumPosStatesMax];
+
+  CBitTreeDecoder               m_PosSlotDecoder[kNumLenToPosStates];
+
+  CReverseBitTreeDecoder2       m_PosDecoders[kNumPosModels];
+  CReverseBitTreeDecoder        m_PosAlignDecoder;
+  
+  LenDecoder m_LenDecoder;
+  LenDecoder m_RepMatchLenDecoder;
+
+  LitDecoder m_LiteralDecoder;
+
+  UINT32 m_DictionarySize;
+  
+  UINT32 m_PosStateMask;
+} LzmaDecoder;
+
+  HRESULT LzmaDecoderCreate(LzmaDecoder *lzmaDecoder);
+
+  HRESULT LzmaDecoderInit(LzmaDecoder *lzmaDecoder);
+
+//static inline  HRESULT LzmaDecoderFlush() { return OutWindowFlush(); }
+
+  HRESULT LzmaDecoderCodeReal( 
+      LzmaDecoder           *lzmaDecoder, 
+//      ISequentialInStream   *in_stream, 
+      UINT64                *anInSize, 
+//      WindowOut             *out_window,
+      UINT64                *anOutSize);
+
+
+  void LzmaDecoderConstructor( LzmaDecoder *lzmaDecoder );
+  
+  HRESULT LzmaDecoderCode( LzmaDecoder *lzmaDecoder, UINT64 *anInSize, UINT64 *anOutSize);
+  HRESULT LzmaDecoderReadCoderProperties(LzmaDecoder *lzmaDecoder );
+
+  HRESULT LzmaDecoderSetDictionarySize(LzmaDecoder *lzmaDecoder, UINT32 aDictionarySize);
+  HRESULT LzmaDecoderSetLiteralProperties(LzmaDecoder *lzmaDecoder, UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits);
+  HRESULT LzmaDecoderSetPosBitsProperties(LzmaDecoder *lzmaDecoder, UINT32 aNumPosStateBits);
+
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/LenCoder.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LenCoder.h
--- linux-2.6.17.6/fs/inflate_lzma/LenCoder.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LenCoder.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,75 @@
+#ifndef __LENCODER_H
+#define __LENCODER_H
+
+#include "BitTreeCoder.h"
+
+
+#define kNumPosStatesBitsMax 4
+#define kNumPosStatesMax 16
+
+
+#define kNumPosStatesBitsEncodingMax 4
+#define kNumPosStatesEncodingMax 16
+
+
+//#define kNumMoveBits 5
+
+#define kNumLenBits 3
+#define kNumLowSymbols (1 << kNumLenBits)
+
+#define kNumMidBits 3
+#define kNumMidSymbols (1 << kNumMidBits)
+
+#define kNumHighBits 8
+
+#define kNumSymbolsTotal (kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits))
+
+typedef struct LenDecoder
+{
+  CBitDecoder       m_Choice;
+  CBitDecoder       m_Choice2;
+  CBitTreeDecoder   m_LowCoder[kNumPosStatesMax];
+  CBitTreeDecoder   m_MidCoder[kNumPosStatesMax];
+  CBitTreeDecoder   m_HighCoder; 
+  UINT32            m_NumPosStates;
+} LenDecoder;
+
+INLINE void LenDecoderCreate(LenDecoder *lenCoder, UINT32 aNumPosStates)
+  { 
+    lenCoder->m_NumPosStates = aNumPosStates; 
+  }
+
+INLINE void LenDecoderInit(LenDecoder *lenCoder)
+  {
+    UINT32 aPosState;
+    BitDecoderInit(&lenCoder->m_Choice);
+    for (aPosState = 0; aPosState < lenCoder->m_NumPosStates; aPosState++)
+    {
+      BitTreeDecoderInit(&lenCoder->m_LowCoder[aPosState],kNumLenBits);
+      BitTreeDecoderInit(&lenCoder->m_MidCoder[aPosState],kNumMidBits);
+    }
+    BitTreeDecoderInit(&lenCoder->m_HighCoder,kNumHighBits);
+    BitDecoderInit(&lenCoder->m_Choice2);
+  }
+
+INLINE UINT32 LenDecode(ISequentialInStream *in_stream, LenDecoder *lenCoder, CRangeDecoder *aRangeDecoder, UINT32 aPosState)
+  {
+    if(BitDecode(in_stream, &lenCoder->m_Choice, aRangeDecoder) == 0)
+      return BitTreeDecode(in_stream, &lenCoder->m_LowCoder[aPosState],aRangeDecoder);
+    else
+    {
+      UINT32 aSymbol = kNumLowSymbols;
+      if(BitDecode(in_stream, &lenCoder->m_Choice2, aRangeDecoder) == 0)
+        aSymbol += BitTreeDecode(in_stream, &lenCoder->m_MidCoder[aPosState],aRangeDecoder);
+      else
+      {
+        aSymbol += kNumMidSymbols;
+        aSymbol += BitTreeDecode(in_stream, &lenCoder->m_HighCoder,aRangeDecoder);
+      }
+      return aSymbol;
+    }
+  }
+
+
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/LiteralCoder.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LiteralCoder.h
--- linux-2.6.17.6/fs/inflate_lzma/LiteralCoder.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/LiteralCoder.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,146 @@
+#ifndef __LITERALCODER_H
+#define __LITERALCODER_H
+
+#include "AriBitCoder.h"
+#include "RCDefs.h"
+
+//BRCM modification start
+#ifdef _HOST_TOOL
+#include "stdio.h"
+#include "malloc.h" 
+#endif
+
+#ifdef _CFE_
+#include "lib_malloc.h"
+#include "lib_printf.h"
+#define malloc(x) KMALLOC(x, 0)
+#define free(x) KFREE(x)
+#endif
+
+#ifdef __KERNEL__
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#define printf  printk
+//#define malloc(x)  kmalloc(x,GFP_KERNEL)
+#define malloc(x)  vmalloc(x)
+#define free(x) vfree(x)
+#endif
+//BRCM modification end
+
+//#define kNumMoveBits 5
+
+typedef struct LitDecoder2
+{
+  CBitDecoder m_Decoders[3][1 << 8];
+} LitDecoder2;
+
+
+INLINE void LitDecoder2Init(LitDecoder2 *litDecoder2)
+  {
+    int i, j;
+    for (i = 0; i < 3; i++)
+      for (j = 1; j < (1 << 8); j++)
+        BitDecoderInit(&litDecoder2->m_Decoders[i][j]);
+  }
+
+INLINE BYTE LitDecoder2DecodeNormal(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder)
+  {
+    UINT32 aSymbol = 1;
+    UINT32 aRange = aRangeDecoder->m_Range;
+    UINT32 aCode = aRangeDecoder->m_Code;        
+    do
+    {
+      RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol)
+    }
+    while (aSymbol < 0x100);
+    aRangeDecoder->m_Range = aRange;
+    aRangeDecoder->m_Code = aCode;
+    return aSymbol;
+  }
+
+INLINE BYTE LitDecoder2DecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder2 *litDecoder2, CRangeDecoder *aRangeDecoder, BYTE aMatchByte)
+  {
+    UINT32 aSymbol = 1;
+    UINT32 aRange = aRangeDecoder->m_Range;
+    UINT32 aCode = aRangeDecoder->m_Code;        
+    do
+    {
+      UINT32 aBit;
+      UINT32 aMatchBit = (aMatchByte >> 7) & 1;
+      aMatchByte <<= 1;
+      RC_GETBIT2(kNumMoveBits, litDecoder2->m_Decoders[1 + aMatchBit][aSymbol], aSymbol, 
+          aBit = 0, aBit = 1)
+      if (aMatchBit != aBit)
+      {
+        while (aSymbol < 0x100)
+        {
+          RC_GETBIT(kNumMoveBits, litDecoder2->m_Decoders[0][aSymbol], aSymbol)
+        }
+        break;
+      }
+    }
+    while (aSymbol < 0x100);
+    aRangeDecoder->m_Range = aRange;
+    aRangeDecoder->m_Code = aCode;
+    return aSymbol;
+  }
+
+
+typedef struct LitDecoder
+{
+  LitDecoder2 *m_Coders;
+  UINT32 m_NumPrevBits;
+  UINT32 m_NumPosBits;
+  UINT32 m_PosMask;
+} LitDecoder;
+
+
+//  LitDecoder(): m_Coders(0) {}
+//  ~LitDecoder()  { Free(); }
+
+/*
+INLINE void LitDecoderFree(LitDecoder *litDecoder)
+  { 
+    free( (char *) litDecoder->m_Coders );
+    litDecoder->m_Coders = 0;
+  }
+*/
+
+INLINE void LitDecoderCreate(LitDecoder *litDecoder, UINT32 aNumPosBits, UINT32 aNumPrevBits)
+  {
+//    LitDecoderFree(litDecoder);
+    UINT32 aNumStates;
+    litDecoder->m_NumPosBits = aNumPosBits;
+    litDecoder->m_PosMask = (1 << aNumPosBits) - 1;
+    litDecoder->m_NumPrevBits = aNumPrevBits;
+    aNumStates = 1 << (aNumPrevBits + aNumPosBits);
+    litDecoder->m_Coders = (LitDecoder2*) malloc( sizeof( LitDecoder2 ) * aNumStates );
+    //printf("malloc in LitDecoderCreate=%d\n",sizeof( LitDecoder2 ) * aNumStates);
+    if (litDecoder->m_Coders == 0)
+        printf( "Error allocating memory for LitDecoder m_Coders!\n" );
+  }
+
+INLINE void LitDecoderInit(LitDecoder *litDecoder)
+  {
+    UINT32 i;
+    UINT32 aNumStates = 1 << (litDecoder->m_NumPrevBits + litDecoder->m_NumPosBits);
+    for (i = 0; i < aNumStates; i++)
+      LitDecoder2Init(&litDecoder->m_Coders[i]);
+  }
+
+INLINE UINT32 LitDecoderGetState(LitDecoder *litDecoder, UINT32 aPos, BYTE aPrevByte)
+  { 
+    return ((aPos & litDecoder->m_PosMask) << litDecoder->m_NumPrevBits) + (aPrevByte >> (8 - litDecoder->m_NumPrevBits)); 
+  }
+
+INLINE BYTE LitDecodeNormal(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte)
+  { 
+    return LitDecoder2DecodeNormal(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder); 
+  }
+
+INLINE BYTE LitDecodeWithMatchByte(ISequentialInStream *in_stream, LitDecoder *litDecoder, CRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte)
+  { 
+      return LitDecoder2DecodeWithMatchByte(in_stream, &litDecoder->m_Coders[LitDecoderGetState(litDecoder, aPos, aPrevByte)], aRangeDecoder, aMatchByte); 
+  }
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/Makefile linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/Makefile
--- linux-2.6.17.6/fs/inflate_lzma/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/Makefile	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,6 @@
+
+BSPOBJS +=               \
+	 7zlzma.o \
+	 LZMADecoder.o \
+	 IInOutStreams.o \
+
diff -Nur linux-2.6.17.6/fs/inflate_lzma/Portable.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/Portable.h
--- linux-2.6.17.6/fs/inflate_lzma/Portable.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/Portable.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,59 @@
+#ifndef __PORTABLE_H
+#define __PORTABLE_H
+
+//BRCM modification
+#ifdef _HOST_TOOL
+#include <string.h>
+#endif
+
+#ifdef _CFE_
+#include <string.h>
+#endif
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+#endif
+
+//bcm
+//#ifdef __GNUC__   
+//#include <types/vxTypesOld.h>
+//#define INLINE static inline
+//#else
+typedef char INT8;
+typedef unsigned char UINT8;
+typedef short INT16;
+typedef unsigned short UINT16;
+typedef int INT32;
+typedef unsigned int UINT32;
+typedef int BOOL;
+#define INLINE static inline
+//#define INLINE static __inline__
+//#endif
+typedef long long INT64;           // %%%% Changed from "long long"
+typedef unsigned long long UINT64; // %%%% Changed from "long long"
+
+typedef UINT8 BYTE;
+typedef UINT16 WORD;
+typedef UINT32 DWORD;
+
+typedef unsigned UINT_PTR;
+#define FALSE 0
+#define TRUE 1
+
+#define HRESULT int
+#define S_OK 0
+#define E_INVALIDARG -1
+#define E_OUTOFMEMORY -2
+#define E_FAIL -3
+#define E_INTERNAL_ERROR -4
+#define E_INVALIDDATA -5
+
+#define MyMin( a, b ) ( a < b ? a : b )
+
+#define MyMax( a, b ) ( a > b ? a : b )
+
+#define kNumMoveBits 5
+
+#define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; }
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/RCDefs.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/RCDefs.h
--- linux-2.6.17.6/fs/inflate_lzma/RCDefs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/RCDefs.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,43 @@
+#ifndef __RCDEFS_H
+#define __RCDEFS_H
+
+#include "AriBitCoder.h"
+
+/*
+#define RC_INIT_VAR                            \
+  UINT32 aRange = aRangeDecoder->m_Range;      \
+  UINT32 aCode = aRangeDecoder->m_Code;        
+
+#define RC_FLUSH_VAR                          \
+  aRangeDecoder->m_Range = aRange;            \
+  aRangeDecoder->m_Code = aCode;
+*/
+
+
+#if 1
+#define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1)                        \
+    {UINT32 aNewBound = (aRange >> kNumBitModelTotalBits) * aProb; \
+    if (aCode < aNewBound)                               \
+    {                                                             \
+      Action0;                                                    \
+      aRange = aNewBound;                                         \
+      aProb += (kBitModelTotal - aProb) >> aNumMoveBits;          \
+      aModelIndex <<= 1;                                          \
+    }                                                             \
+    else                                                          \
+    {                                                             \
+      Action1;                                                    \
+      aRange -= aNewBound;                                        \
+      aCode -= aNewBound;                                          \
+      aProb -= (aProb) >> aNumMoveBits;                           \
+      aModelIndex = (aModelIndex << 1) + 1;                       \
+    }}                                                             \
+    if (aRange < kTopValue)               \
+    {                                                              \
+      aCode = (aCode << 8) | InStreamReadByte(in_stream);   \
+      aRange <<= 8; }
+
+#define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;)               
+#endif
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/RangeCoder.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/RangeCoder.h
--- linux-2.6.17.6/fs/inflate_lzma/RangeCoder.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/RangeCoder.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,56 @@
+#ifndef __COMPRESSION_RANGECODER_H
+#define __COMPRESSION_RANGECODER_H
+
+#include "IInOutStreams.h"
+
+#define kNumTopBits 24
+#define kTopValue (1 << kNumTopBits)
+
+typedef struct CRangeDecoder
+{
+  UINT32  m_Range;
+  UINT32  m_Code;
+} CRangeDecoder;
+
+
+
+INLINE void RangeDecoderInit(
+    ISequentialInStream *in_stream, 
+    CRangeDecoder *rangeDecoder)
+  {
+    int i;
+    rangeDecoder->m_Code = 0;
+    rangeDecoder->m_Range = (UINT32)(-1);
+    for(i = 0; i < 5; i++)
+      rangeDecoder->m_Code = (rangeDecoder->m_Code << 8) | InStreamReadByte(in_stream);
+  }
+
+INLINE UINT32 RangeDecodeDirectBits(
+    ISequentialInStream *in_stream, 
+    CRangeDecoder *rangeDecoder, 
+    UINT32 aNumTotalBits)
+  {
+    UINT32 aRange = rangeDecoder->m_Range;
+    UINT32 aCode = rangeDecoder->m_Code;        
+    UINT32 aResult = 0;
+    UINT32 i;
+    for (i = aNumTotalBits; i > 0; i--)
+    {
+      UINT32 t;
+      aRange >>= 1;
+      t = (aCode - aRange) >> 31;
+      aCode -= aRange & (t - 1);
+      aResult = (aResult << 1) | (1 - t);
+
+      if (aRange < kTopValue)
+      {
+        aCode = (aCode << 8) | InStreamReadByte(in_stream);
+        aRange <<= 8; 
+      }
+    }
+    rangeDecoder->m_Range = aRange;
+    rangeDecoder->m_Code = aCode;
+    return aResult;
+  }
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/WindowOut.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/WindowOut.h
--- linux-2.6.17.6/fs/inflate_lzma/WindowOut.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/WindowOut.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,47 @@
+#ifndef __STREAM_WINDOWOUT_H
+#define __STREAM_WINDOWOUT_H
+
+#include "IInOutStreams.h"
+
+typedef struct WindowOut
+{
+  BYTE  *Buffer;
+  UINT32 Pos;
+} WindowOut;
+
+extern WindowOut out_window;
+
+#define OutWindowInit() \
+  { \
+    out_window.Buffer = (BYTE *) out_stream.data; \
+    out_window.Pos = 0; \
+  }
+
+#define OutWindowFlush() \
+  { \
+    OutStreamSizeSet( out_window.Pos ); \
+  } 
+
+// BRCM modification 
+INLINE void OutWindowCopyBackBlock(UINT32 aDistance, UINT32 aLen)
+  {
+    BYTE   *p = out_window.Buffer + out_window.Pos;
+    UINT32  i;
+    aDistance++;
+    for(i = 0; i < aLen; i++)
+      p[i] = p[i - aDistance];
+    out_window.Pos += aLen;
+  }
+
+
+#define OutWindowPutOneByte(aByte) \
+  { \
+    out_window.Buffer[out_window.Pos++] = aByte; \
+  } 
+
+#define OutWindowGetOneByte(anIndex) \
+     (out_window.Buffer[out_window.Pos + anIndex])
+
+
+
+#endif
diff -Nur linux-2.6.17.6/fs/inflate_lzma/vxTypesOld.h linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/vxTypesOld.h
--- linux-2.6.17.6/fs/inflate_lzma/vxTypesOld.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/inflate_lzma/vxTypesOld.h	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,289 @@
+/* vxTypesOld.h - old VxWorks type definition header */
+
+/* Copyright 1984-1997 Wind River Systems, Inc. */
+
+/*
+modification history
+--------------------
+02c,15aug97,cym  added simnt support.
+02d,26mar97,cdp  added Thumb (ARM7TDMI_T) support.
+02c,28nov96,cdp  added ARM support.
+02b,28sep95,ms	 removed "static __inline__" (SPR #4500)
+02b,12jul95,ism  added simsolaris support
+02a,19mar95,dvs  removed tron references.
+01z,01sep94,ism  fixed comment as per SPR# 1512.
+01y,02dec93,pme  added Am29K family support.
+01x,12jun93,rrr  vxsim.
+02a,26may94,yao  added PPC support.
+01w,09jun93,hdn  added support for I80X86
+01v,12feb93,srh  added C++ versions of FUNCPTR, et al.
+01u,13nov92,dnw  added definition of VOID (SPR #1781)
+01t,02oct92,srh  replaced conditional around volatile, const, and signed so
+                 they won't be elided when __STDC__ is defined.
+                 added __cplusplus to __STDC__ condition.
+01s,22sep92,rrr  added support for c++
+01r,08sep92,smb  made some additions for the MIPS.
+01q,07sep92,smb  added __STDC__ and modes to maintain compatibility with 5.0
+01p,07jul92,rrr  moved STACK_GROW and ENDIAN to vxArch.h
+01o,03jul92,smb  changed name from vxTypes.h.
+01n,26may92,rrr  the tree shuffle
+01m,25nov91,llk  included sys/types.h.
+01l,04oct91,rrr  passed through the ansification filter
+		  -fixed #else and #endif
+		  -removed TINY and UTINY
+		  -changed VOID to void
+		  -changed ASMLANGUAGE to _ASMLANGUAGE
+		  -changed copyright notice
+01k,01oct91,jpb  fixed MIPS conditional for undefined CPU_FAMILY.
+01j,20sep91,wmd  conditionalized out defines for const, unsigned and volatile
+		 for the MIPS architecture.
+01i,02aug91,ajm  added support for MIPS_R3k.
+01h,15may91,gae  added define for "signed" when not available for pre-ANSI.
+01g,29apr91,hdn  added defines and macros for TRON architecture.
+01f,28apr91,del  added defines of __volatile__ and __const__ if !_STDC_
+		 && _GNUC__
+01f,24mar91,del  added INSTR * define for I960.
+01e,28jan91,kdl  added DBLFUNCPTR and FLTFUNCPTR.
+01d,25oct90,dnw  changed void to void except when linting.
+01c,05oct90,shl  added copyright notice.
+                 made #endif ANSI style.
+01b,10aug90,dnw  added VOIDFUNCPTR
+01a,29may90,del  written.
+*/
+
+/*
+DESCRIPTION
+This header file contains a mixture of stuff.
+1) the old style typedefs (ie. POSIX now says they must end with _t).
+   These will be phased out gradually.
+2) a mechanism for getting rid of const warning which are produced by the
+   GNU C compiler. Hopefully, this will be removed in the future.
+3) macros that are so longer needed for vxWorks source code but maybe needed
+   by some customer applications and are therefore provided for backward
+   compatability.
+4) system III typedefs (used by netinet) which do not fit in anywhere else.
+
+*/
+
+#ifndef __INCvxTypesOldh
+#define __INCvxTypesOldh
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "sys/types.h"
+
+/* vxWorks types */
+
+typedef	char		INT8;
+typedef	short		INT16;
+typedef	int		INT32;
+
+typedef	unsigned char	UINT8;
+typedef	unsigned short	UINT16;
+typedef	unsigned int	UINT32;
+
+typedef	unsigned char	UCHAR;
+typedef unsigned short	USHORT;
+typedef	unsigned int	UINT;
+typedef unsigned long	ULONG;
+
+typedef	int		BOOL;
+typedef	int		STATUS;
+typedef int 		ARGINT;
+
+typedef void		VOID;
+
+#ifdef __cplusplus
+typedef int 		(*FUNCPTR) (...);     /* ptr to function returning int */
+typedef void 		(*VOIDFUNCPTR) (...); /* ptr to function returning void */
+typedef double 		(*DBLFUNCPTR) (...);  /* ptr to function returning double*/
+typedef float 		(*FLTFUNCPTR) (...);  /* ptr to function returning float */
+#else
+typedef int 		(*FUNCPTR) ();	   /* ptr to function returning int */
+typedef void 		(*VOIDFUNCPTR) (); /* ptr to function returning void */
+typedef double 		(*DBLFUNCPTR) ();  /* ptr to function returning double*/
+typedef float 		(*FLTFUNCPTR) ();  /* ptr to function returning float */
+#endif			/* _cplusplus */
+
+
+/* This structure and the following definitions are needed to get rid
+   of const warning produced by the GNU C compiler.
+ */
+
+#if defined(__STDC__) || defined(__cplusplus)
+typedef union
+    {
+    long pm_int;
+    void *pm_v;
+    const void *pm_cv;
+    char *pm_c;
+    unsigned char *pm_uc;
+
+    signed char *pm_sc;
+    const char *pm_cc;
+    const unsigned char *pm_cuc;
+    const signed char *pm_csc;
+    short *pm_s;
+    ushort_t *pm_us;
+    const short *pm_cs;
+    const ushort_t *pm_cus;
+    int *pm_i;
+    uint_t *pm_ui;
+    const int *pm_ci;
+    const uint_t *pm_cui;
+    long *pm_l;
+    ulong_t *pm_ul;
+    const long *pm_cl;
+    const ulong_t *pm_cul;
+
+    int8_t *pm_i8;
+    uint8_t *pm_ui8;
+    const int8_t *pm_ci8;
+    const uint8_t *pm_cui8;
+    int16_t *pm_i16;
+    uint16_t *pm_ui16;
+    const int16_t *pm_ci16;
+    const uint16_t *pm_cui16;
+    int32_t *pm_i32;
+    uint32_t *pm_ui32;
+    const int32_t *pm_ci32;
+    const uint32_t *pm_cui32;
+#if _ARCH_MOVE_SIZE > 4
+    int64_t *pm_i64;
+    const int64_t *pm_ci64;
+#if _ARCH_MOVE_SIZE > 8
+    int128_t *pm_i128;
+    const int128_t *pm_ci128;
+#endif
+#endif
+    } pointer_mix_t;
+
+#define CHAR_FROM_CONST(x)	(char *)(x)
+#define VOID_FROM_CONST(x)	(void *)(x)
+
+#endif /* __STDC__ */
+
+#define STACK_DIR		_ARCH_STACK_DIR
+#define ALIGN_MEMORY		_ARCH_ALIGN_MEMORY
+#define ALIGN_STACK		_ARCH_ALIGN_STACK
+#define ALIGN_REGS		_ARCH_ALIGN_REGS
+
+#define	NBBY	8		/* number of bits in a byte */
+
+/* modes - must match O_RDONLY/O_WRONLY/O_RDWR in ioLib.h! */
+
+#define READ            0
+#define WRITE           1
+#define UPDATE          2
+
+/* Select uses bit masks of file descriptors in longs.
+ * These macros manipulate such bit fields (the filesystem macros use chars).
+ * FD_SETSIZE may be defined by the user, but the default here
+ * should be >= maxFiles parameter in iosInit call found in usrConfig.c.
+ * If this define is changed, recompile the source, or else select() will
+ * not work.
+ */
+
+#ifndef	FD_SETSIZE
+#define	FD_SETSIZE	256
+#endif	/* FD_SETSIZE */
+
+typedef long	fd_mask;
+#define NFDBITS	(sizeof(fd_mask) * NBBY)	/* bits per mask */
+#ifndef howmany
+#define	howmany(x, y)	((unsigned int)(((x)+((y)-1)))/(unsigned int)(y))
+#endif	/* howmany */
+
+typedef	struct fd_set
+    {
+    fd_mask	fds_bits[howmany(FD_SETSIZE, NFDBITS)];
+    } fd_set;
+
+#define	FD_SET(n, p)	((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
+#define	FD_CLR(n, p)	((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
+#define	FD_ISSET(n, p)	((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
+#define FD_ZERO(p)	bzero((char *)(p), sizeof(*(p)))
+
+
+/* system III  typedefs (used by netinet) */
+
+typedef	unsigned char	u_char;
+typedef	unsigned short	u_short;
+typedef	unsigned int	u_int;
+typedef	unsigned long	u_long;
+typedef	unsigned short	ushort;
+
+
+/* historical definitions - now obsolete */
+
+typedef char		TBOOL;		/* obsolete */
+
+
+/* architecture dependent typedefs */
+
+#ifdef	CPU_FAMILY
+
+#if	CPU_FAMILY==MC680X0 
+typedef unsigned short INSTR;		/* word-aligned instructions */
+#endif	/* CPU_FAMILY==MC680X0 */
+
+#if	CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS
+typedef unsigned long INSTR;		/* 32 bit word-aligned instructions */
+#endif	/* CPU_FAMILY==SPARC || CPU_FAMILY==MIPS || CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS */
+
+#if	CPU_FAMILY==I960
+typedef	unsigned long INSTR;		/* 32 bit word-aligned instructions */
+#endif	/* CPU_FAMILY==I960 */
+
+#if	CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT
+typedef	unsigned char INSTR;		/* char instructions */
+#endif	/* CPU_FAMILY==I80X86 || CPU_FAMILY==SIMNT */
+
+#if	CPU_FAMILY==AM29XXX
+typedef	unsigned long INSTR;		/* 32 bit word-aligned instructions */
+#endif	/* CPU_FAMILY==AM29XXX */
+
+#if     (CPU_FAMILY==PPC)
+typedef unsigned long INSTR;            /* 32 bit word-aligned instructions */
+#endif  /* (CPU_FAMILY==PPC) */
+
+#if     CPU_FAMILY==ARM
+#if	CPU==ARM7TDMI_T
+typedef unsigned short INSTR;           /* 16 bit instructions */
+#else
+typedef unsigned long INSTR;            /* 32 bit word-aligned instructions */
+#endif
+#endif  /* CPU_FAMILY==ARM */
+
+#endif	/* CPU_FAMILY */
+
+/* ANSI type qualifiers */
+
+#if !defined(__STDC__) && !defined(__cplusplus)
+
+#ifdef  __GNUC__
+#define	volatile	__volatile__
+#define	const		__const__
+#define	signed		__signed__
+#else
+#if     !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS)
+#define	volatile
+#define	const
+#define	signed
+#endif	/* !(defined(CPU_FAMILY) && CPU_FAMILY==MIPS) */
+#endif	/* __GNUC__ */
+
+#endif	/* !defined(__STDC__) && !defined(__cplusplus) */
+
+#if     CPU_FAMILY==MIPS
+#define CHAR_FROM_CONST(x)	(char *)(x)
+#define VOID_FROM_CONST(x)	(void *)(x)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __INCvxTypesOldh */
diff -Nur linux-2.6.17.6/fs/squashfs/Makefile linux-2.6.17.6-bcm_squashfs/fs/squashfs/Makefile
--- linux-2.6.17.6/fs/squashfs/Makefile	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/squashfs/Makefile	2005-02-16 15:49:38.000000000 +0100
@@ -0,0 +1,20 @@
+#
+# Makefile for the linux squashfs routines.
+#
+
+obj-$(CONFIG_SQUASHFS) += squashfs.o
+
+#squashfs-objs := inode.o
+
+# CONFIG_MIPS_BRCM Begin Broadcom changed code.
+
+ifdef CONFIG_ZLIB_FS_INFLATE
+squashfs-objs := inode.o
+else
+ifdef CONFIG_LZMA_FS_INFLATE
+squashfs-objs := inode.o ../inflate_lzma/7zlzma.o ../inflate_lzma/LZMADecoder.o ../inflate_lzma/IInOutStreams.o
+endif
+endif
+
+# CONFIG_MIPS_BRCM End Broadcom changed code.
+
diff -Nur linux-2.6.17.6/fs/squashfs/inode.c linux-2.6.17.6-bcm_squashfs/fs/squashfs/inode.c
--- linux-2.6.17.6/fs/squashfs/inode.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/fs/squashfs/inode.c	2006-10-14 12:03:01.000000000 +0200
@@ -0,0 +1,1659 @@
+/*
+ * Squashfs - a compressed read only filesystem for Linux
+ *
+ * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ *
+ * 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,
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * inode.c
+ */
+ 
+//#define SQUASHFS_1_0_COMPATIBILITY
+
+#include <linux/types.h>
+#include <linux/squashfs_fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/slab.h>
+#include <linux/squashfs_fs_sb.h>
+#include <linux/squashfs_fs_i.h>
+#include <linux/buffer_head.h>
+#include <linux/vfs.h>
+#include <linux/init.h>
+#include <linux/dcache.h>
+#include <asm/uaccess.h>
+#include <linux/wait.h>
+#include <asm/semaphore.h>
+#include <linux/zlib.h>
+#include <linux/blkdev.h>
+#include <linux/vmalloc.h>
+
+#ifdef SQUASHFS_TRACE
+#define TRACE(s, args...)				printk(KERN_NOTICE "SQUASHFS: "s, ## args)
+#else
+#define TRACE(s, args...)				{}
+#endif
+
+#define ERROR(s, args...)				printk(KERN_ERR "SQUASHFS error: "s, ## args)
+
+#define SERROR(s, args...)				if(!silent) printk(KERN_ERR "SQUASHFS error: "s, ## args)
+#define WARNING(s, args...)				printk(KERN_WARNING "SQUASHFS: "s, ## args)
+
+static void squashfs_put_super(struct super_block *);
+static int squashfs_statfs(struct super_block *, struct kstatfs *);
+static int squashfs_symlink_readpage(struct file *file, struct page *page);
+static int squashfs_readpage(struct file *file, struct page *page);
+static int squashfs_readpage4K(struct file *file, struct page *page);
+static int squashfs_readdir(struct file *, void *, filldir_t);
+static struct dentry *squashfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static unsigned int read_data(struct super_block *s, char *buffer,
+		unsigned int index, unsigned int length, int, unsigned int *next_index);
+static int squashfs_get_cached_block(struct super_block *s, char *buffer,
+		unsigned int block, unsigned int offset, int length,
+		unsigned int *next_block, unsigned int *next_offset);
+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode);
+static unsigned int read_blocklist(struct inode *inode, int index, int readahead_blks,
+		char *block_list, char **block_p, unsigned int *bsize);
+static void squashfs_put_super(struct super_block *s);
+static struct super_block *squashfs_get_sb(struct file_system_type *, int, const char *, void *);
+static struct inode *squashfs_alloc_inode(struct super_block *sb);
+static void squashfs_destroy_inode(struct inode *inode);
+static int init_inodecache(void);
+static void destroy_inodecache(void);
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+static int squashfs_readpage_lessthan4K(struct file *file, struct page *page);
+static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode inode);
+static unsigned int read_blocklist_1(struct inode *inode, int index, int readahead_blks,
+		char *block_list, char **block_p, unsigned int *bsize);
+#endif
+
+DECLARE_MUTEX(read_data_mutex);
+
+#ifdef CONFIG_ZLIB_FS_INFLATE
+static z_stream stream;
+#endif
+
+static struct file_system_type squashfs_fs_type = {
+	.owner = THIS_MODULE,
+	.name = "squashfs",
+	.get_sb = squashfs_get_sb,
+	.kill_sb = kill_block_super,
+	.fs_flags = FS_REQUIRES_DEV
+	};
+
+static unsigned char squashfs_filetype_table[] = {
+	DT_UNKNOWN, DT_DIR, DT_REG, DT_LNK, DT_BLK, DT_CHR, DT_FIFO, DT_SOCK
+};
+
+static struct super_operations squashfs_ops = {
+	.alloc_inode = squashfs_alloc_inode,
+	.destroy_inode = squashfs_destroy_inode,
+	.statfs = squashfs_statfs,
+	.put_super = squashfs_put_super,
+};
+
+static struct address_space_operations squashfs_symlink_aops = {
+	.readpage = squashfs_symlink_readpage
+};
+
+static struct address_space_operations squashfs_aops = {
+	.readpage = squashfs_readpage
+};
+
+static struct address_space_operations squashfs_aops_4K = {
+	.readpage = squashfs_readpage4K
+};
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+static struct address_space_operations squashfs_aops_lessthan4K = {
+	.readpage = squashfs_readpage_lessthan4K
+};
+#endif
+
+static struct file_operations squashfs_dir_ops = {
+	.read = generic_read_dir,
+	.readdir = squashfs_readdir
+};
+
+static struct inode_operations squashfs_dir_inode_ops = {
+	.lookup = squashfs_lookup
+};
+
+
+static inline struct squashfs_inode_info *SQUASHFS_I(struct inode *inode)
+{
+	return list_entry(inode, struct squashfs_inode_info, vfs_inode);
+}
+
+
+static unsigned int read_data(struct super_block *s, char *buffer,
+		unsigned int index, unsigned int length, int datablock, unsigned int *next_index)
+{
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+	struct buffer_head *bh[((SQUASHFS_FILE_MAX_SIZE - 1) >> msBlk->devblksize_log2) + 2];
+	unsigned int offset = index & ((1 << msBlk->devblksize_log2) - 1);
+	unsigned int cur_index = index >> msBlk->devblksize_log2;
+	int bytes, avail_bytes, b, k;
+	char *c_buffer;
+	unsigned int compressed;
+	unsigned int c_byte = length;
+
+#ifdef CONFIG_LZMA_FS_INFLATE			
+	extern int decompress_lzma_7z(unsigned char* in_data, unsigned in_size, 
+	                              unsigned char* out_data, unsigned out_size);
+#endif
+	b = 1;
+
+	if(c_byte) {
+		bytes = msBlk->devblksize - offset;
+		if(datablock) {
+			c_buffer = (compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte)) ? msBlk->read_data : buffer;
+			c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
+		} else {
+			c_buffer = (compressed = SQUASHFS_COMPRESSED(c_byte)) ? msBlk->read_data : buffer;
+			c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
+		}
+
+		TRACE("Block @ 0x%x, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte);
+
+		if(!(bh[0] = sb_getblk(s, cur_index)))
+			goto block_release;
+		for(b = 1; bytes < c_byte; b++) {
+			if(!(bh[b] = sb_getblk(s, ++cur_index)))
+				goto block_release;
+			bytes += msBlk->devblksize;
+		}
+		ll_rw_block(READ, b, bh);
+	} else {
+		unsigned short temp;
+		if(!(bh[0] = sb_bread(s, cur_index)))
+			goto read_failure;
+
+		if(msBlk->devblksize - offset == 1) {
+			if(msBlk->swap)
+				((unsigned char *) &temp)[1] = *((unsigned char *) (bh[0]->b_data + offset));
+			else
+				((unsigned char *) &temp)[0] = *((unsigned char *) (bh[0]->b_data + offset));
+			brelse(bh[0]);
+			if(!(bh[0] = sb_bread(s, ++cur_index)))
+				goto read_failure;
+			if(msBlk->swap)
+				((unsigned char *) &temp)[0] = *((unsigned char *) bh[0]->b_data); 
+			else
+				((unsigned char *) &temp)[1] = *((unsigned char *) bh[0]->b_data); 
+			c_byte = temp;
+			offset = 1;
+		}
+		else {
+			if(msBlk->swap) {
+				unsigned short temp;
+				((unsigned char *) &temp)[1] = *((unsigned char *) (bh[0]->b_data + offset));
+				((unsigned char *) &temp)[0] = *((unsigned char *) (bh[0]->b_data + offset + 1)); 
+				c_byte = temp;
+			} else
+				c_byte = *((unsigned short *) (bh[0]->b_data + offset));
+			offset += 2;
+		}
+		if(SQUASHFS_CHECK_DATA(msBlk->sBlk.flags)) {
+			if(offset == msBlk->devblksize) {
+				brelse(bh[0]);
+				if(!(bh[0] = sb_bread(s, ++cur_index)))
+					goto read_failure;
+				offset = 0;
+			}
+			if(*((unsigned char *) (bh[0]->b_data + offset)) != SQUASHFS_MARKER_BYTE) {
+				ERROR("Metadata block marker corrupt @ %x\n", index);
+				brelse(bh[0]);
+				return 0;
+			}
+			offset ++;
+		}
+
+		bytes = msBlk->devblksize - offset;
+		if(datablock) {
+			c_buffer = (compressed = SQUASHFS_COMPRESSED_BLOCK(c_byte)) ? msBlk->read_data : buffer;
+			c_byte = SQUASHFS_COMPRESSED_SIZE_BLOCK(c_byte);
+		} else {
+			c_buffer = (compressed = SQUASHFS_COMPRESSED(c_byte)) ? msBlk->read_data : buffer;
+			c_byte = SQUASHFS_COMPRESSED_SIZE(c_byte);
+		}
+
+		TRACE("Block @ 0x%x, %scompressed size %d\n", index, compressed ? "" : "un", (unsigned int) c_byte);
+
+		for(b = 1; bytes < c_byte; b++) {
+			if(!(bh[b] = sb_getblk(s, ++cur_index)))
+				goto block_release;
+			bytes += msBlk->devblksize;
+		}
+		ll_rw_block(READ, b - 1, bh + 1);
+	}
+
+	if(compressed)
+		down(&read_data_mutex);
+
+	for(bytes = 0, k = 0; k < b; k++) {
+		avail_bytes = (c_byte - bytes) > (msBlk->devblksize - offset) ? msBlk->devblksize - offset : c_byte - bytes;
+		wait_on_buffer(bh[k]);
+		memcpy(c_buffer + bytes, bh[k]->b_data + offset, avail_bytes);
+		bytes += avail_bytes;
+		offset = 0;
+		brelse(bh[k]);
+	}
+
+	/*
+	 * uncompress block
+	 */
+	if(compressed) {
+#ifdef CONFIG_ZLIB_FS_INFLATE
+		int zlib_err;
+
+		stream.next_in = c_buffer;
+		stream.avail_in = c_byte;
+		stream.next_out = buffer;
+		stream.avail_out = msBlk->read_size;
+		if(((zlib_err = zlib_inflateInit(&stream)) != Z_OK) ||
+				((zlib_err = zlib_inflate(&stream, Z_FINISH)) != Z_STREAM_END) ||
+				((zlib_err = zlib_inflateEnd(&stream)) != Z_OK)) {
+			ERROR("zlib_fs returned unexpected result 0x%x\n", zlib_err);
+			bytes = 0;
+		} else
+			bytes = stream.total_out;
+#endif
+#ifdef CONFIG_LZMA_FS_INFLATE
+		TRACE("Calling decompress_lzma_7z: buffer_in size=%d, buffer_out size=%d\n",
+				c_byte, msBlk->read_size);
+		if ((bytes = decompress_lzma_7z(c_buffer, c_byte, buffer, msBlk->read_size)) < 0) {
+			ERROR("lzma_fs error while decompressing!\n");
+			bytes = 0;
+                } else
+			bytes = msBlk->read_size;
+		TRACE("Done with decompress_lzma_7z: output size=%d\n", bytes); 			
+#endif
+		up(&read_data_mutex);
+	}
+
+	if(next_index)
+		*next_index = index + c_byte + (length ? 0 : (SQUASHFS_CHECK_DATA(msBlk->sBlk.flags) ? 3 : 2));
+
+	return bytes;
+
+block_release:
+	while(--b >= 0) brelse(bh[b]);
+
+read_failure:
+	ERROR("sb_bread failed reading block 0x%x\n", cur_index);
+	return 0;
+}
+
+
+static int squashfs_get_cached_block(struct super_block *s, char *buffer,
+		unsigned int block, unsigned int offset, int length,
+		unsigned int *next_block, unsigned int *next_offset)
+{
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+	int n, i, bytes, return_length = length;
+	unsigned int next_index;
+
+	TRACE("Entered squashfs_get_cached_block [%x:%x]\n", block, offset);
+
+	for(;;) {
+		for(i = 0; i < SQUASHFS_CACHED_BLKS; i++) 
+			if(msBlk->block_cache[i].block == block)
+				break; 
+		
+		down(&msBlk->block_cache_mutex);
+		if(i == SQUASHFS_CACHED_BLKS) {
+			/* read inode header block */
+			for(i = msBlk->next_cache, n = SQUASHFS_CACHED_BLKS; n ; n --, i = (i + 1) % SQUASHFS_CACHED_BLKS)
+				if(msBlk->block_cache[i].block != SQUASHFS_USED_BLK)
+					break;
+			if(n == 0) {
+				wait_queue_t wait;
+
+				init_waitqueue_entry(&wait, current);
+				add_wait_queue(&msBlk->waitq, &wait);
+ 				up(&msBlk->block_cache_mutex);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule();
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&msBlk->waitq, &wait);
+				continue;
+			}
+			msBlk->next_cache = (i + 1) % SQUASHFS_CACHED_BLKS;
+
+			if(msBlk->block_cache[i].block == SQUASHFS_INVALID_BLK) {
+				if(!(msBlk->block_cache[i].data = (unsigned char *)
+							kmalloc(SQUASHFS_METADATA_SIZE, GFP_KERNEL))) {
+					ERROR("Failed to allocate cache block\n");
+					up(&msBlk->block_cache_mutex);
+					return 0;
+				}
+			}
+	
+			msBlk->block_cache[i].block = SQUASHFS_USED_BLK;
+			up(&msBlk->block_cache_mutex);
+			if(!(msBlk->block_cache[i].length = read_data(s, msBlk->block_cache[i].data, block, 0, 0,
+							&next_index))) {
+				ERROR("Unable to read cache block [%x:%x]\n", block, offset);
+				return 0;
+			}
+			down(&msBlk->block_cache_mutex);
+			wake_up(&msBlk->waitq);
+			msBlk->block_cache[i].block = block;
+			msBlk->block_cache[i].next_index = next_index;
+			TRACE("Read cache block [%x:%x]\n", block, offset);
+		}
+
+		if(msBlk->block_cache[i].block != block) {
+			up(&msBlk->block_cache_mutex);
+			continue;
+		}
+
+		if((bytes = msBlk->block_cache[i].length - offset) >= length) {
+			if(buffer)
+				memcpy(buffer, msBlk->block_cache[i].data + offset, length);
+			if(msBlk->block_cache[i].length - offset == length) {
+				*next_block = msBlk->block_cache[i].next_index;
+				*next_offset = 0;
+			} else {
+				*next_block = block;
+				*next_offset = offset + length;
+			}
+	
+			up(&msBlk->block_cache_mutex);
+			return return_length;
+		} else {
+			if(buffer) {
+				memcpy(buffer, msBlk->block_cache[i].data + offset, bytes);
+				buffer += bytes;
+			}
+			block = msBlk->block_cache[i].next_index;
+			up(&msBlk->block_cache_mutex);
+			length -= bytes;
+			offset = 0;
+		}
+	}
+}
+
+
+static int get_fragment_location(struct super_block *s, unsigned int fragment, unsigned int *fragment_start_block, unsigned int *fragment_size)
+{
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+	unsigned int start_block = msBlk->fragment_index[SQUASHFS_FRAGMENT_INDEX(fragment)];
+	int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment);
+	squashfs_fragment_entry fragment_entry;
+
+	if(msBlk->swap) {
+		squashfs_fragment_entry sfragment_entry;
+
+		if(!squashfs_get_cached_block(s, (char *) &sfragment_entry, start_block, offset,
+					sizeof(sfragment_entry), &start_block, &offset))
+			return 0;
+		SQUASHFS_SWAP_FRAGMENT_ENTRY(&fragment_entry, &sfragment_entry);
+	} else
+		if(!squashfs_get_cached_block(s, (char *) &fragment_entry, start_block, offset,
+					sizeof(fragment_entry), &start_block, &offset))
+			return 0;
+
+	*fragment_start_block = fragment_entry.start_block;
+	*fragment_size = fragment_entry.size;
+
+	return 1;
+}
+
+
+void release_cached_fragment(squashfs_sb_info *msBlk, struct squashfs_fragment_cache *fragment)
+{
+	down(&msBlk->fragment_mutex);
+	fragment->locked --;
+	wake_up(&msBlk->fragment_wait_queue);
+	up(&msBlk->fragment_mutex);
+}
+
+
+struct squashfs_fragment_cache *get_cached_fragment(struct super_block *s, unsigned int start_block, int length)
+{
+	int i, n;
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+
+	for(;;) {
+		down(&msBlk->fragment_mutex);
+		for(i = 0; i < SQUASHFS_CACHED_FRAGMENTS && msBlk->fragment[i].block != start_block; i++);
+		if(i == SQUASHFS_CACHED_FRAGMENTS) {
+			for(i = msBlk->next_fragment, n = SQUASHFS_CACHED_FRAGMENTS;
+				n && msBlk->fragment[i].locked; n--, i = (i + 1) % SQUASHFS_CACHED_FRAGMENTS);
+
+			if(n == 0) {
+				wait_queue_t wait;
+
+				init_waitqueue_entry(&wait, current);
+				add_wait_queue(&msBlk->fragment_wait_queue, &wait);
+				up(&msBlk->fragment_mutex);
+				set_current_state(TASK_UNINTERRUPTIBLE);
+				schedule();
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&msBlk->fragment_wait_queue, &wait);
+				continue;
+			}
+			msBlk->next_fragment = (msBlk->next_fragment + 1) % SQUASHFS_CACHED_FRAGMENTS;
+			
+			if(msBlk->fragment[i].data == NULL)
+				if(!(msBlk->fragment[i].data = (unsigned char *)
+							kmalloc(SQUASHFS_FILE_MAX_SIZE, GFP_KERNEL))) {
+					ERROR("Failed to allocate fragment cache block\n");
+					up(&msBlk->fragment_mutex);
+					return NULL;
+				}
+
+			msBlk->fragment[i].block = SQUASHFS_INVALID_BLK;
+			msBlk->fragment[i].locked = 1;
+			up(&msBlk->fragment_mutex);
+			if(!(msBlk->fragment[i].length = read_data(s, msBlk->fragment[i].data, start_block, length,
+							1, NULL))) {
+				ERROR("Unable to read fragment cache block [%x]\n", start_block);
+				msBlk->fragment[i].locked = 0;
+				return NULL;
+			}
+			msBlk->fragment[i].block = start_block;
+			TRACE("New fragment %d, start block %d, locked %d\n", i, msBlk->fragment[i].block, msBlk->fragment[i].locked);
+			return &msBlk->fragment[i];
+		}
+
+		msBlk->fragment[i].locked ++;
+		up(&msBlk->fragment_mutex);
+		
+		TRACE("Got fragment %d, start block %d, locked %d\n", i, msBlk->fragment[i].block, msBlk->fragment[i].locked);
+		return &msBlk->fragment[i];
+	}
+}
+
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+static struct inode *squashfs_iget_1(struct super_block *s, squashfs_inode inode)
+{
+	struct inode *i = new_inode(s);
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+	squashfs_super_block *sBlk = &msBlk->sBlk;
+	unsigned int block = SQUASHFS_INODE_BLK(inode) + sBlk->inode_table_start;
+	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+	unsigned int next_block, next_offset;
+	squashfs_base_inode_header_1 inodeb;
+
+	TRACE("Entered squashfs_iget_1\n");
+
+	if(msBlk->swap) {
+		squashfs_base_inode_header_1 sinodeb;
+
+		if(!squashfs_get_cached_block(s, (char *) &sinodeb, block,  offset,
+					sizeof(sinodeb), &next_block, &next_offset))
+			goto failed_read;
+		SQUASHFS_SWAP_BASE_INODE_HEADER_1(&inodeb, &sinodeb, sizeof(sinodeb));
+	} else
+		if(!squashfs_get_cached_block(s, (char *) &inodeb, block,  offset,
+					sizeof(inodeb), &next_block, &next_offset))
+			goto failed_read;
+
+	i->i_nlink = 1;
+
+	i->i_mtime.tv_sec = sBlk->mkfs_time;
+	i->i_atime.tv_sec = sBlk->mkfs_time;
+	i->i_ctime.tv_sec = sBlk->mkfs_time;
+
+	if(inodeb.inode_type != SQUASHFS_IPC_TYPE)
+		i->i_uid = msBlk->uid[((inodeb.inode_type - 1) / SQUASHFS_TYPES) * 16 + inodeb.uid];
+	i->i_ino = SQUASHFS_MK_VFS_INODE(block - sBlk->inode_table_start, offset);
+
+	i->i_mode = inodeb.mode;
+
+	switch(inodeb.inode_type == SQUASHFS_IPC_TYPE ? SQUASHFS_IPC_TYPE : (inodeb.inode_type - 1) % SQUASHFS_TYPES + 1) {
+		case SQUASHFS_FILE_TYPE: {
+			squashfs_reg_inode_header_1 inodep;
+
+			if(msBlk->swap) {
+				squashfs_reg_inode_header_1 sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_REG_INODE_HEADER_1(&inodep, &sinodep);
+			} else
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = inodep.file_size;
+			i->i_fop = &generic_ro_fops;
+			if(sBlk->block_size > 4096)
+				i->i_data.a_ops = &squashfs_aops;
+			else if(sBlk->block_size == 4096)
+				i->i_data.a_ops = &squashfs_aops_4K;
+			else
+				i->i_data.a_ops = &squashfs_aops_lessthan4K;
+			i->i_mode |= S_IFREG;
+			i->i_mtime.tv_sec = inodep.mtime;
+			i->i_atime.tv_sec = inodep.mtime;
+			i->i_ctime.tv_sec = inodep.mtime;
+			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+			i->i_blksize = PAGE_CACHE_SIZE;
+			SQUASHFS_I(i)->fragment_start_block = SQUASHFS_INVALID_BLK;
+			SQUASHFS_I(i)->fragment_offset = 0;
+			SQUASHFS_I(i)->start_block = inodep.start_block;
+			SQUASHFS_I(i)->block_list_start = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+			TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset, inodep.start_block, next_block, next_offset);
+			break;
+		}
+		case SQUASHFS_DIR_TYPE: {
+			squashfs_dir_inode_header_1 inodep;
+
+			if(msBlk->swap) {
+				squashfs_dir_inode_header_1 sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DIR_INODE_HEADER_1(&inodep, &sinodep);
+			} else
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = inodep.file_size;
+			i->i_op = &squashfs_dir_inode_ops;
+			i->i_fop = &squashfs_dir_ops;
+			i->i_mode |= S_IFDIR;
+			i->i_mtime.tv_sec = inodep.mtime;
+			i->i_atime.tv_sec = inodep.mtime;
+			i->i_ctime.tv_sec = inodep.mtime;
+			SQUASHFS_I(i)->start_block = inodep.start_block;
+			SQUASHFS_I(i)->offset = inodep.offset;
+			TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset,
+					inodep.start_block, inodep.offset);
+			break;
+		}
+		case SQUASHFS_SYMLINK_TYPE: {
+			squashfs_symlink_inode_header_1 inodep;
+	
+			if(msBlk->swap) {
+				squashfs_symlink_inode_header_1 sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(&inodep, &sinodep);
+			} else
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = inodep.symlink_size;
+			i->i_op = &page_symlink_inode_operations;
+			i->i_data.a_ops = &squashfs_symlink_aops;
+			i->i_mode |= S_IFLNK;
+			SQUASHFS_I(i)->start_block = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+			TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n",
+				SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset);
+			break;
+		 }
+		 case SQUASHFS_BLKDEV_TYPE:
+		 case SQUASHFS_CHRDEV_TYPE: {
+			squashfs_dev_inode_header_1 inodep;
+
+			if(msBlk->swap) {
+				squashfs_dev_inode_header_1 sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DEV_INODE_HEADER_1(&inodep, &sinodep);
+			} else	
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = 0;
+			i->i_mode |= (inodeb.inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK;
+			init_special_inode(i, i->i_mode, old_decode_dev(inodep.rdev));
+			TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep.rdev);
+			break;
+		 }
+		 case SQUASHFS_IPC_TYPE: {
+			squashfs_ipc_inode_header_1 inodep;
+
+			if(msBlk->swap) {
+				squashfs_ipc_inode_header_1 sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_IPC_INODE_HEADER_1(&inodep, &sinodep);
+			} else	
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = 0;
+			i->i_mode |= (inodep.type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK;
+			i->i_uid = msBlk->uid[inodep.offset * 16 + inodeb.uid];
+			init_special_inode(i, i->i_mode, 0);
+			break;
+		 }
+		 default:
+			ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb.inode_type);
+				goto failed_read1;
+	}
+	
+	if(inodeb.guid == 15)
+		i->i_gid = i->i_uid;
+	else
+		i->i_gid = msBlk->guid[inodeb.guid];
+
+	return i;
+
+failed_read:
+	ERROR("Unable to read inode [%x:%x]\n", block, offset);
+
+failed_read1:
+	return NULL;
+}
+#endif
+
+
+static struct inode *squashfs_iget(struct super_block *s, squashfs_inode inode)
+{
+	struct inode *i = new_inode(s);
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)s->s_fs_info;
+	squashfs_super_block *sBlk = &msBlk->sBlk;
+	unsigned int block = SQUASHFS_INODE_BLK(inode) + sBlk->inode_table_start;
+	unsigned int offset = SQUASHFS_INODE_OFFSET(inode);
+	unsigned int next_block, next_offset;
+	squashfs_base_inode_header inodeb;
+
+	TRACE("Entered squashfs_iget\n");
+
+	if(msBlk->swap) {
+		squashfs_base_inode_header sinodeb;
+
+		if(!squashfs_get_cached_block(s, (char *) &sinodeb, block,  offset,
+					sizeof(sinodeb), &next_block, &next_offset))
+			goto failed_read;
+		SQUASHFS_SWAP_BASE_INODE_HEADER(&inodeb, &sinodeb, sizeof(sinodeb));
+	} else
+		if(!squashfs_get_cached_block(s, (char *) &inodeb, block,  offset,
+					sizeof(inodeb), &next_block, &next_offset))
+			goto failed_read;
+
+	i->i_nlink = 1;
+
+	i->i_mtime.tv_sec = sBlk->mkfs_time;
+	i->i_atime.tv_sec = sBlk->mkfs_time;
+	i->i_ctime.tv_sec = sBlk->mkfs_time;
+
+	i->i_uid = msBlk->uid[inodeb.uid];
+	i->i_ino = SQUASHFS_MK_VFS_INODE(block - sBlk->inode_table_start, offset);
+
+	i->i_mode = inodeb.mode;
+
+	switch(inodeb.inode_type) {
+		case SQUASHFS_FILE_TYPE: {
+			squashfs_reg_inode_header inodep;
+
+			if(msBlk->swap) {
+				squashfs_reg_inode_header sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_REG_INODE_HEADER(&inodep, &sinodep);
+			} else
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			SQUASHFS_I(i)->fragment_start_block = SQUASHFS_INVALID_BLK;
+			if(inodep.fragment != SQUASHFS_INVALID_BLK && !get_fragment_location(s, inodep.fragment,
+							&SQUASHFS_I(i)->fragment_start_block, &SQUASHFS_I(i)->fragment_size))
+				goto failed_read;
+
+			SQUASHFS_I(i)->fragment_offset = inodep.offset;
+			i->i_size = inodep.file_size;
+			i->i_fop = &generic_ro_fops;
+			if(sBlk->block_size > 4096)
+				i->i_data.a_ops = &squashfs_aops;
+			else
+				i->i_data.a_ops = &squashfs_aops_4K;
+			i->i_mode |= S_IFREG;
+			i->i_mtime.tv_sec = inodep.mtime;
+			i->i_atime.tv_sec = inodep.mtime;
+			i->i_ctime.tv_sec = inodep.mtime;
+			i->i_blocks = ((i->i_size - 1) >> 9) + 1;
+			i->i_blksize = PAGE_CACHE_SIZE;
+			SQUASHFS_I(i)->start_block = inodep.start_block;
+			SQUASHFS_I(i)->block_list_start = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+			TRACE("File inode %x:%x, start_block %x, block_list_start %x, offset %x\n",
+					SQUASHFS_INODE_BLK(inode), offset, inodep.start_block, next_block, next_offset);
+			break;
+		}
+		case SQUASHFS_DIR_TYPE: {
+			squashfs_dir_inode_header inodep;
+
+			if(msBlk->swap) {
+				squashfs_dir_inode_header sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DIR_INODE_HEADER(&inodep, &sinodep);
+			} else
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = inodep.file_size;
+			i->i_op = &squashfs_dir_inode_ops;
+			i->i_fop = &squashfs_dir_ops;
+			i->i_mode |= S_IFDIR;
+			i->i_mtime.tv_sec = inodep.mtime;
+			i->i_atime.tv_sec = inodep.mtime;
+			i->i_ctime.tv_sec = inodep.mtime;
+			SQUASHFS_I(i)->start_block = inodep.start_block;
+			SQUASHFS_I(i)->offset = inodep.offset;
+			TRACE("Directory inode %x:%x, start_block %x, offset %x\n", SQUASHFS_INODE_BLK(inode), offset,
+					inodep.start_block, inodep.offset);
+			break;
+		}
+		case SQUASHFS_SYMLINK_TYPE: {
+			squashfs_symlink_inode_header inodep;
+	
+			if(msBlk->swap) {
+				squashfs_symlink_inode_header sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_SYMLINK_INODE_HEADER(&inodep, &sinodep);
+			} else
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = inodep.symlink_size;
+			i->i_op = &page_symlink_inode_operations;
+			i->i_data.a_ops = &squashfs_symlink_aops;
+			i->i_mode |= S_IFLNK;
+			SQUASHFS_I(i)->start_block = next_block;
+			SQUASHFS_I(i)->offset = next_offset;
+			TRACE("Symbolic link inode %x:%x, start_block %x, offset %x\n",
+				SQUASHFS_INODE_BLK(inode), offset, next_block, next_offset);
+			break;
+		 }
+		 case SQUASHFS_BLKDEV_TYPE:
+		 case SQUASHFS_CHRDEV_TYPE: {
+			squashfs_dev_inode_header inodep;
+
+			if(msBlk->swap) {
+				squashfs_dev_inode_header sinodep;
+
+				if(!squashfs_get_cached_block(s, (char *) &sinodep, block,  offset, sizeof(sinodep),
+							&next_block, &next_offset))
+					goto failed_read;
+				SQUASHFS_SWAP_DEV_INODE_HEADER(&inodep, &sinodep);
+			} else	
+				if(!squashfs_get_cached_block(s, (char *) &inodep, block,  offset, sizeof(inodep),
+							&next_block, &next_offset))
+					goto failed_read;
+
+			i->i_size = 0;
+			i->i_mode |= (inodeb.inode_type == SQUASHFS_CHRDEV_TYPE) ? S_IFCHR : S_IFBLK;
+			init_special_inode(i, i->i_mode, old_decode_dev(inodep.rdev));
+			TRACE("Device inode %x:%x, rdev %x\n", SQUASHFS_INODE_BLK(inode), offset, inodep.rdev);
+			break;
+		 }
+		 case SQUASHFS_FIFO_TYPE:
+		 case SQUASHFS_SOCKET_TYPE: {
+			i->i_size = 0;
+			i->i_mode |= (inodeb.inode_type == SQUASHFS_FIFO_TYPE) ? S_IFIFO : S_IFSOCK;
+			init_special_inode(i, i->i_mode, 0);
+			break;
+		 }
+		 default:
+			ERROR("Unknown inode type %d in squashfs_iget!\n", inodeb.inode_type);
+				goto failed_read1;
+	}
+	
+	if(inodeb.guid == SQUASHFS_GUIDS)
+		i->i_gid = i->i_uid;
+	else
+		i->i_gid = msBlk->guid[inodeb.guid];
+
+	return i;
+
+failed_read:
+	ERROR("Unable to read inode [%x:%x]\n", block, offset);
+
+failed_read1:
+	return NULL;
+}
+
+
+static int squashfs_fill_super(struct super_block *s,
+		void *data, int silent)
+{
+	squashfs_sb_info *msBlk;
+	squashfs_super_block *sBlk;
+	int i;
+	char b[BDEVNAME_SIZE];
+
+	TRACE("Entered squashfs_read_superblock\n");
+
+	if(!(msBlk = (squashfs_sb_info *) s->s_fs_info = (void *) kmalloc(sizeof(squashfs_sb_info), GFP_KERNEL))) {
+		ERROR("Failed to allocate superblock\n");
+		return -ENOMEM;
+	}
+	sBlk = &msBlk->sBlk;
+	
+	msBlk->devblksize = sb_min_blocksize(s, BLOCK_SIZE);
+	msBlk->devblksize_log2 = ffz(~msBlk->devblksize);
+
+	init_MUTEX(&msBlk->read_page_mutex);
+	init_MUTEX(&msBlk->block_cache_mutex);
+	init_MUTEX(&msBlk->fragment_mutex);
+	
+	init_waitqueue_head(&msBlk->waitq);
+	init_waitqueue_head(&msBlk->fragment_wait_queue);
+
+	if(!read_data(s, (char *) sBlk, SQUASHFS_START, sizeof(squashfs_super_block) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
+		SERROR("unable to read superblock\n");
+		goto failed_mount;
+	}
+
+	/* Check it is a SQUASHFS superblock */
+	msBlk->swap = 0;
+	if((s->s_magic = sBlk->s_magic) != SQUASHFS_MAGIC) {
+		if(sBlk->s_magic == SQUASHFS_MAGIC_SWAP) {
+			squashfs_super_block sblk;
+			WARNING("Mounting a different endian SQUASHFS filesystem on %s\n", bdevname(s->s_bdev, b));
+			SQUASHFS_SWAP_SUPER_BLOCK(&sblk, sBlk);
+			memcpy(sBlk, &sblk, sizeof(squashfs_super_block));
+			msBlk->swap = 1;
+		} else  {
+			SERROR("Can't find a SQUASHFS superblock on %s\n", bdevname(s->s_bdev, b));
+			goto failed_mount;
+		}
+	}
+
+	/* Check the MAJOR & MINOR versions */
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+	if((sBlk->s_major != 1) && (sBlk->s_major != 2 || sBlk->s_minor > SQUASHFS_MINOR)) {
+		SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (1 : x) or (2 : <= %d)\n",
+				sBlk->s_major, sBlk->s_minor, SQUASHFS_MINOR);
+		goto failed_mount;
+	}
+	if(sBlk->s_major == 1)
+		sBlk->block_size = sBlk->block_size_1;
+#else
+	if(sBlk->s_major != SQUASHFS_MAJOR || sBlk->s_minor > SQUASHFS_MINOR) {
+		SERROR("Major/Minor mismatch, filesystem is (%d:%d), I support (%d: <= %d)\n",
+				sBlk->s_major, sBlk->s_minor, SQUASHFS_MAJOR, SQUASHFS_MINOR);
+		goto failed_mount;
+	}
+#endif
+
+	TRACE("Found valid superblock on %s\n", bdevname(s->s_bdev, b));
+	TRACE("Inodes are %scompressed\n", SQUASHFS_UNCOMPRESSED_INODES(sBlk->flags) ? "un" : "");
+	TRACE("Data is %scompressed\n", SQUASHFS_UNCOMPRESSED_DATA(sBlk->flags) ? "un" : "");
+	TRACE("Check data is %s present in the filesystem\n", SQUASHFS_CHECK_DATA(sBlk->flags) ? "" : "not");
+	TRACE("Filesystem size %d bytes\n", sBlk->bytes_used);
+	TRACE("Block size %d\n", sBlk->block_size);
+	TRACE("Number of inodes %d\n", sBlk->inodes);
+	if(sBlk->s_major > 1)
+		TRACE("Number of fragments %d\n", sBlk->fragments);
+	TRACE("Number of uids %d\n", sBlk->no_uids);
+	TRACE("Number of gids %d\n", sBlk->no_guids);
+	TRACE("sBlk->inode_table_start %x\n", sBlk->inode_table_start);
+	TRACE("sBlk->directory_table_start %x\n", sBlk->directory_table_start);
+		if(sBlk->s_major > 1)
+	TRACE("sBlk->fragment_table_start %x\n", sBlk->fragment_table_start);
+	TRACE("sBlk->uid_start %x\n", sBlk->uid_start);
+
+	s->s_flags |= MS_RDONLY;
+	s->s_op = &squashfs_ops;
+
+	/* Init inode_table block pointer array */
+	if(!(msBlk->block_cache = (squashfs_cache *) kmalloc(sizeof(squashfs_cache) * SQUASHFS_CACHED_BLKS, GFP_KERNEL))) {
+		ERROR("Failed to allocate block cache\n");
+		goto failed_mount;
+	}
+
+	for(i = 0; i < SQUASHFS_CACHED_BLKS; i++)
+		msBlk->block_cache[i].block = SQUASHFS_INVALID_BLK;
+
+	msBlk->next_cache = 0;
+
+	/* Allocate read_data block */
+	msBlk->read_size = (sBlk->block_size < SQUASHFS_METADATA_SIZE) ? SQUASHFS_METADATA_SIZE : sBlk->block_size;
+	if(!(msBlk->read_data = (char *) kmalloc(msBlk->read_size, GFP_KERNEL))) {
+		ERROR("Failed to allocate read_data block\n");
+		goto failed_mount1;
+	}
+
+	/* Allocate read_page block */
+	if(sBlk->block_size > PAGE_CACHE_SIZE && 
+	   !(msBlk->read_page = (char *) kmalloc(sBlk->block_size, GFP_KERNEL))) {
+		ERROR("Failed to allocate read_page block\n");
+		goto failed_mount2;
+	}
+
+	/* Allocate uid and gid tables */
+	if(!(msBlk->uid = (squashfs_uid *) kmalloc((sBlk->no_uids +
+		sBlk->no_guids) * sizeof(squashfs_uid), GFP_KERNEL))) {
+		ERROR("Failed to allocate uid/gid table\n");
+		goto failed_mount3;
+	}
+	msBlk->guid = msBlk->uid + sBlk->no_uids;
+   
+	if(msBlk->swap) {
+		squashfs_uid suid[sBlk->no_uids + sBlk->no_guids];
+
+		if(!read_data(s, (char *) &suid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) *
+				sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
+			SERROR("unable to read uid/gid table\n");
+			goto failed_mount4;
+		}
+		SQUASHFS_SWAP_DATA(msBlk->uid, suid, (sBlk->no_uids + sBlk->no_guids), (sizeof(squashfs_uid) * 8));
+	} else
+		if(!read_data(s, (char *) msBlk->uid, sBlk->uid_start, ((sBlk->no_uids + sBlk->no_guids) *
+				sizeof(squashfs_uid)) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
+			SERROR("unable to read uid/gid table\n");
+			goto failed_mount4;
+		}
+
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+	if(sBlk->s_major == 1) {
+		msBlk->iget = squashfs_iget_1;
+		msBlk->read_blocklist = read_blocklist_1;
+		msBlk->fragment = (struct squashfs_fragment_cache *) msBlk->fragment_index = NULL;
+		goto allocate_root;
+	}
+#endif
+	msBlk->iget = squashfs_iget;
+	msBlk->read_blocklist = read_blocklist;
+
+	if(!(msBlk->fragment = (struct squashfs_fragment_cache *) kmalloc(sizeof(struct squashfs_fragment_cache) * SQUASHFS_CACHED_FRAGMENTS, GFP_KERNEL))) {
+		ERROR("Failed to allocate fragment block cache\n");
+		goto failed_mount4;
+	}
+
+	for(i = 0; i < SQUASHFS_CACHED_FRAGMENTS; i++) {
+		msBlk->fragment[i].locked = 0;
+		msBlk->fragment[i].block = SQUASHFS_INVALID_BLK;
+		msBlk->fragment[i].data = NULL;
+	}
+
+	msBlk->next_fragment = 0;
+
+	/* Allocate fragment index table */
+	if(!(msBlk->fragment_index = (squashfs_fragment_index *) kmalloc(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments), GFP_KERNEL))) {
+		ERROR("Failed to allocate uid/gid table\n");
+		goto failed_mount5;
+	}
+   
+	if(SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments) &&
+	 	!read_data(s, (char *) msBlk->fragment_index, sBlk->fragment_table_start,
+		SQUASHFS_FRAGMENT_INDEX_BYTES(sBlk->fragments) | SQUASHFS_COMPRESSED_BIT, 0, NULL)) {
+			SERROR("unable to read fragment index table\n");
+			goto failed_mount6;
+	}
+
+	if(msBlk->swap) {
+		int i;
+		squashfs_fragment_index fragment;
+
+		for(i = 0; i < SQUASHFS_FRAGMENT_INDEXES(sBlk->fragments); i++) {
+			SQUASHFS_SWAP_FRAGMENT_INDEXES((&fragment), &msBlk->fragment_index[i], 1);
+			msBlk->fragment_index[i] = fragment;
+		}
+	}
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+allocate_root:
+#endif
+	if(!(s->s_root = d_alloc_root((msBlk->iget)(s, sBlk->root_inode)))) {
+		ERROR("Root inode create failed\n");
+		goto failed_mount5;
+	}
+
+	TRACE("Leaving squashfs_read_super\n");
+	return 0;
+
+failed_mount6:
+	kfree(msBlk->fragment_index);
+failed_mount5:
+	kfree(msBlk->fragment);
+failed_mount4:
+	kfree(msBlk->uid);
+failed_mount3:
+	kfree(msBlk->read_page);
+failed_mount2:
+	kfree(msBlk->read_data);
+failed_mount1:
+	kfree(msBlk->block_cache);
+failed_mount:
+	kfree(s->s_fs_info);
+	s->s_fs_info = NULL;
+	return -EINVAL;
+}
+
+
+static int squashfs_statfs(struct super_block *s, struct kstatfs *buf)
+{
+	squashfs_super_block *sBlk = &((squashfs_sb_info *)s->s_fs_info)->sBlk;
+
+	TRACE("Entered squashfs_statfs\n");
+	buf->f_type = SQUASHFS_MAGIC;
+	buf->f_bsize = sBlk->block_size;
+	buf->f_blocks = ((sBlk->bytes_used - 1) >> sBlk->block_log) + 1;
+	buf->f_bfree = buf->f_bavail = 0;
+	buf->f_files = sBlk->inodes;
+	buf->f_ffree = 0;
+	buf->f_namelen = SQUASHFS_NAME_LEN;
+	return 0;
+}
+
+
+static int squashfs_symlink_readpage(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	int index = page->index << PAGE_CACHE_SHIFT, length, bytes;
+	int block = SQUASHFS_I(inode)->start_block;
+	int offset = SQUASHFS_I(inode)->offset;
+	void *pageaddr = kmap(page);
+
+	TRACE("Entered squashfs_symlink_readpage, page index %d, start block %x, offset %x\n",
+		page->index, SQUASHFS_I(inode)->start_block, SQUASHFS_I(inode)->offset);
+
+	for(length = 0; length < index; length += bytes) {
+		if(!(bytes = squashfs_get_cached_block(inode->i_sb, NULL, block, offset,
+					PAGE_CACHE_SIZE, &block, &offset))) {
+			ERROR("Unable to read symbolic link [%x:%x]\n", block, offset);
+			goto skip_read;
+		}
+	}
+
+	if(length != index) {
+		ERROR("(squashfs_symlink_readpage) length != index\n");
+		bytes = 0;
+		goto skip_read;
+	}
+
+	bytes = (inode->i_size - length) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : inode->i_size - length;
+	if(!(bytes = squashfs_get_cached_block(inode->i_sb, pageaddr, block, offset, bytes, &block, &offset)))
+		ERROR("Unable to read symbolic link [%x:%x]\n", block, offset);
+
+skip_read:
+	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
+	kunmap(page);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+
+	return 0;
+}
+
+
+#define SIZE 256
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+static unsigned int read_blocklist_1(struct inode *inode, int index, int readahead_blks,
+		char *block_list, char **block_p, unsigned int *bsize)
+{
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info;
+	unsigned short *block_listp;
+	int i = 0;
+	int block_ptr = SQUASHFS_I(inode)->block_list_start;
+	int offset = SQUASHFS_I(inode)->offset;
+	int block = SQUASHFS_I(inode)->start_block;
+
+	for(;;) {
+		int blocks = (index + readahead_blks - i);
+		if(blocks > (SIZE >> 1)) {
+			if((index - i) <= (SIZE >> 1))
+				blocks = index - i;
+			else
+				blocks = SIZE >> 1;
+		}
+
+		if(msBlk->swap) {
+			unsigned char sblock_list[SIZE];
+			if(!squashfs_get_cached_block(inode->i_sb, (char *) sblock_list, block_ptr, offset, blocks << 1, &block_ptr, &offset)) {
+				ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
+				return 0;
+			}
+			SQUASHFS_SWAP_SHORTS(((unsigned short *)block_list), ((unsigned short *)sblock_list), blocks);
+		} else
+			if(!squashfs_get_cached_block(inode->i_sb, (char *) block_list, block_ptr, offset, blocks << 1, &block_ptr, &offset)) {
+				ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
+				return 0;
+			}
+		for(block_listp = (unsigned short *) block_list; i < index && blocks; i ++, block_listp ++, blocks --)
+			block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
+		if(blocks >= readahead_blks)
+			break;
+	}
+
+	if(bsize)
+		*bsize = SQUASHFS_COMPRESSED_SIZE(*block_listp) | (!SQUASHFS_COMPRESSED(*block_listp) ? SQUASHFS_COMPRESSED_BIT_BLOCK : 0);
+	else
+		(unsigned short *) *block_p = block_listp;
+	return block;
+}
+#endif
+
+
+static unsigned int read_blocklist(struct inode *inode, int index, int readahead_blks,
+		char *block_list, char **block_p, unsigned int *bsize)
+{
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info;
+	unsigned int *block_listp;
+	int i = 0;
+	int block_ptr = SQUASHFS_I(inode)->block_list_start;
+	int offset = SQUASHFS_I(inode)->offset;
+	int block = SQUASHFS_I(inode)->start_block;
+
+	for(;;) {
+		int blocks = (index + readahead_blks - i);
+		if(blocks > (SIZE >> 2)) {
+			if((index - i) <= (SIZE >> 2))
+				blocks = index - i;
+			else
+				blocks = SIZE >> 2;
+		}
+
+		if(msBlk->swap) {
+			unsigned char sblock_list[SIZE];
+			if(!squashfs_get_cached_block(inode->i_sb, (char *) sblock_list, block_ptr, offset, blocks << 2, &block_ptr, &offset)) {
+				ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
+				return 0;
+			}
+			SQUASHFS_SWAP_INTS(((unsigned int *)block_list), ((unsigned int *)sblock_list), blocks);
+		} else
+			if(!squashfs_get_cached_block(inode->i_sb, (char *) block_list, block_ptr, offset, blocks << 2, &block_ptr, &offset)) {
+				ERROR("Unable to read block list [%d:%x]\n", block_ptr, offset);
+				return 0;
+			}
+		for(block_listp = (unsigned int *) block_list; i < index && blocks; i ++, block_listp ++, blocks --)
+			block += SQUASHFS_COMPRESSED_SIZE_BLOCK(*block_listp);
+		if(blocks >= readahead_blks)
+			break;
+	}
+
+	*bsize = *block_listp;
+	return block;
+}
+
+
+static int squashfs_readpage(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info;
+	squashfs_super_block *sBlk = &msBlk->sBlk;
+	unsigned char block_list[SIZE];
+	unsigned int bsize, block, i = 0, bytes = 0, byte_offset = 0;
+	int index = page->index >> (sBlk->block_log - PAGE_CACHE_SHIFT);
+ 	void *pageaddr = kmap(page);
+	struct squashfs_fragment_cache *fragment;
+	char *data_ptr = msBlk->read_page;
+	
+	int mask = (1 << (sBlk->block_log - PAGE_CACHE_SHIFT)) - 1;
+	int start_index = page->index & ~mask;
+	int end_index = start_index | mask;
+
+	TRACE("Entered squashfs_readpage, page index %x, start block %x\n", (unsigned int) page->index,
+		SQUASHFS_I(inode)->start_block);
+
+	if(page->index >= ((inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT))
+		goto skip_read;
+
+	if(SQUASHFS_I(inode)->fragment_start_block == SQUASHFS_INVALID_BLK || index < (inode->i_size >> sBlk->block_log)) {
+		if((block = (msBlk->read_blocklist)(inode, index, 1, block_list, NULL, &bsize)) == 0)
+			goto skip_read;
+
+		down(&msBlk->read_page_mutex);
+		if(!(bytes = read_data(inode->i_sb, msBlk->read_page, block, bsize, 1, NULL))) {
+			ERROR("Unable to read page, block %x, size %x\n", block, bsize);
+			up(&msBlk->read_page_mutex);
+			goto skip_read;
+		}
+	} else {
+		if((fragment = get_cached_fragment(inode->i_sb, SQUASHFS_I(inode)->fragment_start_block, SQUASHFS_I(inode)->fragment_size)) == NULL) {
+			ERROR("Unable to read page, block %x, size %x\n", SQUASHFS_I(inode)->fragment_start_block, (int) SQUASHFS_I(inode)->fragment_size);
+			goto skip_read;
+		}
+		bytes = SQUASHFS_I(inode)->fragment_offset + (inode->i_size & (sBlk->block_size - 1));
+		byte_offset = SQUASHFS_I(inode)->fragment_offset;
+		data_ptr = fragment->data;
+	}
+
+	for(i = start_index; i <= end_index && byte_offset < bytes; i++, byte_offset += PAGE_CACHE_SIZE) {
+		struct page *push_page;
+		int available_bytes = (bytes - byte_offset) > PAGE_CACHE_SIZE ? PAGE_CACHE_SIZE : bytes - byte_offset;
+
+		TRACE("bytes %d, i %d, byte_offset %d, available_bytes %d\n", bytes, i, byte_offset, available_bytes);
+
+		if(i == page->index)  {
+			memcpy(pageaddr, data_ptr + byte_offset, available_bytes);
+			memset(pageaddr + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes);
+			kunmap(page);
+			flush_dcache_page(page);
+			SetPageUptodate(page);
+			unlock_page(page);
+		} else if((push_page = grab_cache_page_nowait(page->mapping, i))) {
+ 			void *pageaddr = kmap(push_page);
+			memcpy(pageaddr, data_ptr + byte_offset, available_bytes);
+			memset(pageaddr + available_bytes, 0, PAGE_CACHE_SIZE - available_bytes);
+			kunmap(push_page);
+			flush_dcache_page(push_page);
+			SetPageUptodate(push_page);
+			unlock_page(push_page);
+			page_cache_release(push_page);
+		}
+	}
+
+	if(SQUASHFS_I(inode)->fragment_start_block == SQUASHFS_INVALID_BLK || index < (inode->i_size >> sBlk->block_log))
+		up(&msBlk->read_page_mutex);
+	else
+		release_cached_fragment(msBlk, fragment);
+
+	return 0;
+
+skip_read:
+	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
+	kunmap(page);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+
+	return 0;
+}
+
+
+static int squashfs_readpage4K(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info;
+	squashfs_super_block *sBlk = &msBlk->sBlk;
+	unsigned char block_list[SIZE];
+	unsigned int bsize, block, bytes = 0;
+ 	void *pageaddr = kmap(page);
+	
+	TRACE("Entered squashfs_readpage4K, page index %x, start block %x\n", (unsigned int) page->index,
+		SQUASHFS_I(inode)->start_block);
+
+	if(page->index >= ((inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT))
+		goto skip_read;
+
+	if(page->index < (inode->i_size >> sBlk->block_log)) {
+		block = (msBlk->read_blocklist)(inode, page->index, 1, block_list, NULL, &bsize);
+
+		if(!(bytes = read_data(inode->i_sb, pageaddr, block, bsize, 1, NULL)))
+			ERROR("Unable to read page, block %x, size %x\n", block, bsize);
+	} else {
+		struct squashfs_fragment_cache *fragment;
+
+		if((fragment = get_cached_fragment(inode->i_sb, SQUASHFS_I(inode)->fragment_start_block, SQUASHFS_I(inode)->fragment_size)) == NULL)
+			ERROR("Unable to read page, block %x, size %x\n", SQUASHFS_I(inode)->fragment_start_block, (int) SQUASHFS_I(inode)->fragment_size);
+		else {
+			bytes = inode->i_size & (sBlk->block_size - 1);
+			memcpy(pageaddr, fragment->data + SQUASHFS_I(inode)->fragment_offset, bytes);
+			release_cached_fragment(msBlk, fragment);
+		}
+	}
+
+skip_read:
+	memset(pageaddr + bytes, 0, PAGE_CACHE_SIZE - bytes);
+	kunmap(page);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+
+	return 0;
+}
+
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+static int squashfs_readpage_lessthan4K(struct file *file, struct page *page)
+{
+	struct inode *inode = page->mapping->host;
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)inode->i_sb->s_fs_info;
+	squashfs_super_block *sBlk = &msBlk->sBlk;
+	unsigned char block_list[SIZE];
+	unsigned short *block_listp, block, bytes = 0;
+	int index = page->index << (PAGE_CACHE_SHIFT - sBlk->block_log);
+	int file_blocks = ((inode->i_size - 1) >> sBlk->block_log) + 1;
+	int readahead_blks = 1 << (PAGE_CACHE_SHIFT - sBlk->block_log);
+ 	void *pageaddr = kmap(page);
+	
+	int i_end = index + (1 << (PAGE_CACHE_SHIFT - sBlk->block_log));
+	int byte;
+
+	TRACE("Entered squashfs_readpage_lessthan4K, page index %x, start block %x\n", (unsigned int) page->index,
+		SQUASHFS_I(inode)->start_block);
+
+	block = read_blocklist_1(inode, index, readahead_blks, block_list, (char **) &block_listp, NULL);
+
+	if(i_end > file_blocks)
+		i_end = file_blocks;
+
+	while(index < i_end) {
+		if(!(byte = read_data(inode->i_sb, pageaddr, block, *block_listp, 0, NULL))) {
+			ERROR("Unable to read page, block %x, size %x\n", block, *block_listp);
+			goto skip_read;
+		}
+		block += SQUASHFS_COMPRESSED_SIZE(*block_listp);
+		pageaddr += byte;
+		bytes += byte;
+		index ++;
+		block_listp ++;
+	}
+
+skip_read:
+	memset(pageaddr, 0, PAGE_CACHE_SIZE - bytes);
+	kunmap(page);
+	flush_dcache_page(page);
+	SetPageUptodate(page);
+	unlock_page(page);
+
+	return 0;
+}
+#endif
+
+
+static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+	struct inode *i = file->f_dentry->d_inode;
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)i->i_sb->s_fs_info;
+	squashfs_super_block *sBlk = &msBlk->sBlk;
+	int next_block = SQUASHFS_I(i)->start_block + sBlk->directory_table_start, next_offset =
+		SQUASHFS_I(i)->offset, length = 0, dirs_read = 0, dir_count;
+	squashfs_dir_header dirh;
+	char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN + 1];
+	squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
+
+	TRACE("Entered squashfs_readdir [%x:%x]\n", next_block, next_offset);
+
+	lock_kernel();
+	while(length < i->i_size) {
+		/* read directory header */
+		if(msBlk->swap) {
+			squashfs_dir_header sdirh;
+			if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block,
+						next_offset, sizeof(sdirh), &next_block, &next_offset))
+				goto failed_read;
+			length += sizeof(sdirh);
+			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
+		} else {
+			if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block,
+						next_offset, sizeof(dirh), &next_block, &next_offset))
+				goto failed_read;
+			length += sizeof(dirh);
+		}
+
+		dir_count = dirh.count + 1;
+		while(dir_count--) {
+			if(msBlk->swap) {
+				squashfs_dir_entry sdire;
+				if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire, next_block,
+							next_offset, sizeof(sdire), &next_block, &next_offset))
+					goto failed_read;
+				length += sizeof(sdire);
+				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
+			} else {
+				if(!squashfs_get_cached_block(i->i_sb, (char *) dire, next_block,
+							next_offset, sizeof(*dire), &next_block, &next_offset))
+					goto failed_read;
+				length += sizeof(*dire);
+			}
+
+			if(!squashfs_get_cached_block(i->i_sb, dire->name, next_block,
+						next_offset, dire->size + 1, &next_block, &next_offset))
+				goto failed_read;
+			length += dire->size + 1;
+
+			if(file->f_pos >= length)
+				continue;
+
+			dire->name[dire->size + 1] = '\0';
+
+			TRACE("Calling filldir(%x, %s, %d, %d, %x:%x, %d)\n", (unsigned int) dirent,
+			dire->name, dire->size + 1, (int) file->f_pos,
+			dirh.start_block, dire->offset, squashfs_filetype_table[dire->type]);
+
+			if(filldir(dirent, dire->name, dire->size + 1, file->f_pos, SQUASHFS_MK_VFS_INODE(dirh.start_block,
+							dire->offset), squashfs_filetype_table[dire->type]) < 0) {
+				TRACE("Filldir returned less than 0\n");
+				unlock_kernel();
+				return dirs_read;
+			}
+
+			file->f_pos = length;
+			dirs_read ++;
+		}
+	}
+
+	unlock_kernel();
+	return dirs_read;
+
+failed_read:
+	unlock_kernel();
+	ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);
+	return 0;
+}
+
+
+static struct dentry *squashfs_lookup(struct inode *i, struct dentry *dentry, struct nameidata *nd)
+{
+	const char *name =dentry->d_name.name;
+	int len = dentry->d_name.len;
+	struct inode *inode = NULL;
+	squashfs_sb_info *msBlk = (squashfs_sb_info *)i->i_sb->s_fs_info;
+	squashfs_super_block *sBlk = &msBlk->sBlk;
+	int next_block = SQUASHFS_I(i)->start_block + sBlk->directory_table_start, next_offset =
+		SQUASHFS_I(i)->offset, length = 0, dir_count;
+	squashfs_dir_header dirh;
+	char buffer[sizeof(squashfs_dir_entry) + SQUASHFS_NAME_LEN];
+	squashfs_dir_entry *dire = (squashfs_dir_entry *) buffer;
+
+	TRACE("Entered squashfs_lookup [%x:%x]\n", next_block, next_offset);
+
+	lock_kernel();
+	while(length < i->i_size) {
+		/* read directory header */
+		if(msBlk->swap) {
+			squashfs_dir_header sdirh;
+			if(!squashfs_get_cached_block(i->i_sb, (char *) &sdirh, next_block, next_offset,
+						sizeof(sdirh), &next_block, &next_offset))
+				goto failed_read;
+			length += sizeof(sdirh);
+			SQUASHFS_SWAP_DIR_HEADER(&dirh, &sdirh);
+		} else {
+			if(!squashfs_get_cached_block(i->i_sb, (char *) &dirh, next_block, next_offset,
+						sizeof(dirh), &next_block, &next_offset))
+				goto failed_read;
+			length += sizeof(dirh);
+		}
+
+		dir_count = dirh.count + 1;
+		while(dir_count--) {
+			if(msBlk->swap) {
+				squashfs_dir_entry sdire;
+				if(!squashfs_get_cached_block(i->i_sb, (char *) &sdire,
+							next_block,next_offset, sizeof(sdire), &next_block, &next_offset))
+					goto failed_read;
+				length += sizeof(sdire);
+				SQUASHFS_SWAP_DIR_ENTRY(dire, &sdire);
+			} else {
+				if(!squashfs_get_cached_block(i->i_sb, (char *) dire,
+							next_block,next_offset, sizeof(*dire), &next_block, &next_offset))
+					goto failed_read;
+				length += sizeof(*dire);
+			}
+
+			if(!squashfs_get_cached_block(i->i_sb, dire->name,
+						next_block, next_offset, dire->size + 1, &next_block, &next_offset))
+				goto failed_read;
+			length += dire->size + 1;
+
+			if((len == dire->size + 1) && !strncmp(name, dire->name, len)) {
+				squashfs_inode ino = SQUASHFS_MKINODE(dirh.start_block, dire->offset);
+
+				TRACE("calling squashfs_iget for directory entry %s, inode %x:%x\n",
+						name, dirh.start_block, dire->offset);
+
+				inode = (msBlk->iget)(i->i_sb, ino);
+
+				goto exit_loop;
+			}
+		}
+	}
+
+exit_loop:
+	d_add(dentry, inode);
+	unlock_kernel();
+	return ERR_PTR(0);
+
+failed_read:
+	ERROR("Unable to read directory block [%x:%x]\n", next_block, next_offset);
+	goto exit_loop;
+}
+
+
+static void squashfs_put_super(struct super_block *s)
+{
+	if(s->s_fs_info) {
+		squashfs_sb_info *sbi = (squashfs_sb_info *) s->s_fs_info;
+		if(sbi->block_cache) kfree(sbi->block_cache);
+		if(sbi->read_data) kfree(sbi->read_data);
+		if(sbi->read_page) kfree(sbi->read_page);
+		if(sbi->uid) kfree(sbi->uid);
+		if(sbi->fragment) kfree(sbi->fragment);
+		if(sbi->fragment_index) kfree(sbi->fragment_index);
+		kfree(s->s_fs_info);
+		s->s_fs_info = NULL;
+	}
+}
+
+
+static struct super_block *squashfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
+{
+	return get_sb_bdev(fs_type, flags, dev_name, data, squashfs_fill_super);
+}
+
+
+static int __init init_squashfs_fs(void)
+{
+	int err = init_inodecache();
+	if(err)
+		return err;
+
+#ifdef CONFIG_ZLIB_FS_INFLATE	
+	if(!(stream.workspace = (char *) vmalloc(zlib_inflate_workspacesize()))) {
+		ERROR("Failed to allocate zlib workspace\n");
+		destroy_inodecache();
+		return -ENOMEM;
+	}
+#endif	
+
+	if((err = register_filesystem(&squashfs_fs_type))) {
+#ifdef CONFIG_ZLIB_FS_INFLATE		
+		vfree(stream.workspace);
+#endif		
+		destroy_inodecache();
+	}
+
+	return err;
+}
+
+
+static void __exit exit_squashfs_fs(void)
+{
+#ifdef CONFIG_ZLIB_FS_INFLATE	
+	vfree(stream.workspace);
+#endif	
+	unregister_filesystem(&squashfs_fs_type);
+	destroy_inodecache();
+}
+
+
+static kmem_cache_t * squashfs_inode_cachep;
+
+
+static struct inode *squashfs_alloc_inode(struct super_block *sb)
+{
+	struct squashfs_inode_info *ei;
+	ei = (struct squashfs_inode_info *)kmem_cache_alloc(squashfs_inode_cachep, SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	return &ei->vfs_inode;
+}
+
+
+static void squashfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(squashfs_inode_cachep, SQUASHFS_I(inode));
+}
+
+
+static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+{
+	struct squashfs_inode_info *ei = (struct squashfs_inode_info *) foo;
+
+	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
+	    SLAB_CTOR_CONSTRUCTOR)
+		inode_init_once(&ei->vfs_inode);
+}
+ 
+
+static int init_inodecache(void)
+{
+	squashfs_inode_cachep = kmem_cache_create("squashfs_inode_cache",
+					     sizeof(struct squashfs_inode_info),
+					     0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT,
+					     init_once, NULL);
+	if (squashfs_inode_cachep == NULL)
+		return -ENOMEM;
+	return 0;
+}
+
+
+static void destroy_inodecache(void)
+{
+	if (kmem_cache_destroy(squashfs_inode_cachep))
+		printk(KERN_INFO "squashfs_inode_cache: not all structures were freed\n");
+}
+
+
+module_init(init_squashfs_fs);
+module_exit(exit_squashfs_fs);
+MODULE_DESCRIPTION("squashfs, a compressed read-only filesystem");
+MODULE_AUTHOR("Phillip Lougher <plougher@users.sourceforge.net>");
+MODULE_LICENSE("GPL");
diff -Nur linux-2.6.17.6/include/linux/squashfs_fs.h linux-2.6.17.6-bcm_squashfs/include/linux/squashfs_fs.h
--- linux-2.6.17.6/include/linux/squashfs_fs.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/include/linux/squashfs_fs.h	2005-04-29 03:43:56.000000000 +0200
@@ -0,0 +1,474 @@
+#ifndef SQUASHFS_FS
+#define SQUASHFS_FS
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ *
+ * 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,
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs.h
+ */
+
+#define SQUASHFS_MAJOR			2
+#define SQUASHFS_MINOR			0
+#define SQUASHFS_MAGIC			0x73717368
+#define SQUASHFS_MAGIC_SWAP		0x68737173
+#define SQUASHFS_START			0
+
+/* size of metadata (inode and directory) blocks */
+#define SQUASHFS_METADATA_SIZE		8192
+#define SQUASHFS_METADATA_LOG		13
+
+/* default size of data blocks */
+#define SQUASHFS_FILE_SIZE		65536
+#define SQUASHFS_FILE_LOG		16
+
+#define SQUASHFS_FILE_MAX_SIZE		65536
+
+/* Max number of uids and gids */
+#define SQUASHFS_UIDS			256
+#define SQUASHFS_GUIDS			255
+
+/* Max length of filename (not 255) */
+#define SQUASHFS_NAME_LEN		256
+
+#define SQUASHFS_INVALID		((long long) 0xffffffffffff)
+#define SQUASHFS_INVALID_BLK		((long long) 0xffffffff)
+#define SQUASHFS_USED_BLK		((long long) 0xfffffffe)
+
+/* Filesystem flags */
+#define SQUASHFS_NOI			0
+#define SQUASHFS_NOD			1
+#define SQUASHFS_CHECK			2
+#define SQUASHFS_NOF			3
+#define SQUASHFS_NO_FRAG		4
+#define SQUASHFS_ALWAYS_FRAG		5
+#define SQUASHFS_DUPLICATE		6
+#define SQUASHFS_BIT(flag, bit)		((flag >> bit) & 1)
+#define SQUASHFS_UNCOMPRESSED_INODES(flags)	SQUASHFS_BIT(flags, SQUASHFS_NOI)
+#define SQUASHFS_UNCOMPRESSED_DATA(flags)	SQUASHFS_BIT(flags, SQUASHFS_NOD)
+#define SQUASHFS_UNCOMPRESSED_FRAGMENTS(flags)	SQUASHFS_BIT(flags, SQUASHFS_NOF)
+#define SQUASHFS_NO_FRAGMENTS(flags)		SQUASHFS_BIT(flags, SQUASHFS_NO_FRAG)
+#define SQUASHFS_ALWAYS_FRAGMENTS(flags)	SQUASHFS_BIT(flags, SQUASHFS_ALWAYS_FRAG)
+#define SQUASHFS_DUPLICATES(flags)		SQUASHFS_BIT(flags, SQUASHFS_DUPLICATE)
+#define SQUASHFS_CHECK_DATA(flags)		SQUASHFS_BIT(flags, SQUASHFS_CHECK)
+#define SQUASHFS_MKFLAGS(noi, nod, check_data, nof, no_frag, always_frag, duplicate_checking)	(noi | (nod << 1) | (check_data << 2) | (nof << 3) | (no_frag << 4) | (always_frag << 5) | (duplicate_checking << 6))
+
+/* Max number of types and file types */
+#define SQUASHFS_DIR_TYPE		1
+#define SQUASHFS_FILE_TYPE		2
+#define SQUASHFS_SYMLINK_TYPE		3
+#define SQUASHFS_BLKDEV_TYPE		4
+#define SQUASHFS_CHRDEV_TYPE		5
+#define SQUASHFS_FIFO_TYPE		6
+#define SQUASHFS_SOCKET_TYPE		7
+
+/* 1.0 filesystem type definitions */
+#define SQUASHFS_TYPES			5
+#define SQUASHFS_IPC_TYPE		0
+
+/* Flag whether block is compressed or uncompressed, bit is set if block is uncompressed */
+#define SQUASHFS_COMPRESSED_BIT		(1 << 15)
+#define SQUASHFS_COMPRESSED_SIZE(B)	(((B) & ~SQUASHFS_COMPRESSED_BIT) ? \
+					(B) & ~SQUASHFS_COMPRESSED_BIT : SQUASHFS_COMPRESSED_BIT)
+
+#define SQUASHFS_COMPRESSED(B)		(!((B) & SQUASHFS_COMPRESSED_BIT))
+
+#define SQUASHFS_COMPRESSED_BIT_BLOCK		(1 << 24)
+#define SQUASHFS_COMPRESSED_SIZE_BLOCK(B)	(((B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK) ? \
+					(B) & ~SQUASHFS_COMPRESSED_BIT_BLOCK : SQUASHFS_COMPRESSED_BIT_BLOCK)
+
+#define SQUASHFS_COMPRESSED_BLOCK(B)		(!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK))
+
+/*
+ * Inode number ops.  Inodes consist of a compressed block number, and an uncompressed
+ * offset within that block
+ */
+#define SQUASHFS_INODE_BLK(a)		((unsigned int) ((a) >> 16))
+#define SQUASHFS_INODE_OFFSET(a)	((unsigned int) ((a) & 0xffff))
+#define SQUASHFS_MKINODE(A, B)		((squashfs_inode)(((squashfs_inode) (A) << 16)\
+					+ (B)))
+
+/* Compute 32 bit VFS inode number from squashfs inode number */
+#define SQUASHFS_MK_VFS_INODE(a, b)	((unsigned int) (((a) << 8) + ((b) >> 2) + 1))
+
+/* Translate between VFS mode and squashfs mode */
+#define SQUASHFS_MODE(a)		((a) & 0xfff)
+
+/* fragment and fragment table defines */
+typedef unsigned int			squashfs_fragment_index;
+#define SQUASHFS_FRAGMENT_BYTES(A)	(A * sizeof(squashfs_fragment_entry))
+#define SQUASHFS_FRAGMENT_INDEX(A)	(SQUASHFS_FRAGMENT_BYTES(A) / SQUASHFS_METADATA_SIZE)
+#define SQUASHFS_FRAGMENT_INDEX_OFFSET(A)	(SQUASHFS_FRAGMENT_BYTES(A) % SQUASHFS_METADATA_SIZE)
+#define SQUASHFS_FRAGMENT_INDEXES(A)	((SQUASHFS_FRAGMENT_BYTES(A) + SQUASHFS_METADATA_SIZE - 1) / SQUASHFS_METADATA_SIZE)
+#define SQUASHFS_FRAGMENT_INDEX_BYTES(A)	(SQUASHFS_FRAGMENT_INDEXES(A) * sizeof(squashfs_fragment_index))
+#define SQUASHFS_CACHED_FRAGMENTS	3
+
+/* cached data constants for filesystem */
+#define SQUASHFS_CACHED_BLKS		8
+
+#define SQUASHFS_MAX_FILE_SIZE_LOG	32
+#define SQUASHFS_MAX_FILE_SIZE		((long long) 1 << (SQUASHFS_MAX_FILE_SIZE_LOG - 1))
+
+#define SQUASHFS_MARKER_BYTE		0xff
+
+/*
+ * definitions for structures on disk
+ */
+
+typedef unsigned int		squashfs_block;
+typedef long long		squashfs_inode;
+
+typedef unsigned int		squashfs_uid;
+
+typedef struct squashfs_super_block {
+	unsigned int		s_magic;
+	unsigned int		inodes;
+	unsigned int		bytes_used;
+	unsigned int		uid_start;
+	unsigned int		guid_start;
+	unsigned int		inode_table_start;
+	unsigned int		directory_table_start;
+	unsigned int		s_major:16;
+	unsigned int		s_minor:16;
+	unsigned int		block_size_1:16;
+	unsigned int		block_log:16;
+	unsigned int		flags:8;
+	unsigned int		no_uids:8;
+	unsigned int		no_guids:8;
+	unsigned int		mkfs_time /* time of filesystem creation */;
+	squashfs_inode		root_inode;
+	unsigned int		block_size;
+	unsigned int		fragments;
+	unsigned int		fragment_table_start;
+} __attribute__ ((packed)) squashfs_super_block;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+} __attribute__ ((packed)) squashfs_base_inode_header;
+
+typedef squashfs_base_inode_header squashfs_ipc_inode_header;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned short		rdev;
+} __attribute__ ((packed)) squashfs_dev_inode_header;
+	
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned short		symlink_size;
+	char			symlink[0];
+} __attribute__ ((packed)) squashfs_symlink_inode_header;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned int		mtime;
+	squashfs_block		start_block;
+	unsigned int		fragment;
+	unsigned int		offset;
+	unsigned int		file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+	unsigned short		block_list[0];
+} __attribute__ ((packed)) squashfs_reg_inode_header;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:8; /* index into uid table */
+	unsigned int		guid:8; /* index into guid table */
+	unsigned int		file_size:19;
+	unsigned int		offset:13;
+	unsigned int		mtime;
+	unsigned int		start_block:24;
+} __attribute__  ((packed)) squashfs_dir_inode_header;
+
+typedef union {
+	squashfs_base_inode_header	base;
+	squashfs_dev_inode_header	dev;
+	squashfs_symlink_inode_header	symlink;
+	squashfs_reg_inode_header	reg;
+	squashfs_dir_inode_header	dir;
+	squashfs_ipc_inode_header	ipc;
+} squashfs_inode_header;
+	
+typedef struct {
+	unsigned int		offset:13;
+	unsigned int		type:3;
+	unsigned int		size:8;
+	char			name[0];
+} __attribute__ ((packed)) squashfs_dir_entry;
+
+typedef struct {
+	unsigned int		count:8;
+	unsigned int		start_block:24;
+} __attribute__ ((packed)) squashfs_dir_header;
+
+
+typedef struct {
+	unsigned int		start_block;
+	unsigned int		size;
+} __attribute__ ((packed)) squashfs_fragment_entry;
+
+extern int squashfs_uncompress_block(void *d, int dstlen, void *s, int srclen);
+extern int squashfs_uncompress_init(void);
+extern int squashfs_uncompress_exit(void);
+
+/*
+ * macros to convert each packed bitfield structure from little endian to big
+ * endian and vice versa.  These are needed when creating or using a filesystem on a
+ * machine with different byte ordering to the target architecture.
+ *
+ */
+
+#define SQUASHFS_SWAP_SUPER_BLOCK(s, d) {\
+	SQUASHFS_MEMSET(s, d, sizeof(squashfs_super_block));\
+	SQUASHFS_SWAP((s)->s_magic, d, 0, 32);\
+	SQUASHFS_SWAP((s)->inodes, d, 32, 32);\
+	SQUASHFS_SWAP((s)->bytes_used, d, 64, 32);\
+	SQUASHFS_SWAP((s)->uid_start, d, 96, 32);\
+	SQUASHFS_SWAP((s)->guid_start, d, 128, 32);\
+	SQUASHFS_SWAP((s)->inode_table_start, d, 160, 32);\
+	SQUASHFS_SWAP((s)->directory_table_start, d, 192, 32);\
+	SQUASHFS_SWAP((s)->s_major, d, 224, 16);\
+	SQUASHFS_SWAP((s)->s_minor, d, 240, 16);\
+	SQUASHFS_SWAP((s)->block_size_1, d, 256, 16);\
+	SQUASHFS_SWAP((s)->block_log, d, 272, 16);\
+	SQUASHFS_SWAP((s)->flags, d, 288, 8);\
+	SQUASHFS_SWAP((s)->no_uids, d, 296, 8);\
+	SQUASHFS_SWAP((s)->no_guids, d, 304, 8);\
+	SQUASHFS_SWAP((s)->mkfs_time, d, 312, 32);\
+	SQUASHFS_SWAP((s)->root_inode, d, 344, 64);\
+	SQUASHFS_SWAP((s)->block_size, d, 408, 32);\
+	SQUASHFS_SWAP((s)->fragments, d, 440, 32);\
+	SQUASHFS_SWAP((s)->fragment_table_start, d, 472, 32);\
+}
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, n) {\
+	SQUASHFS_MEMSET(s, d, n);\
+	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+	SQUASHFS_SWAP((s)->uid, d, 16, 8);\
+	SQUASHFS_SWAP((s)->guid, d, 24, 8);\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER(s, d) SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_ipc_inode_header))
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dev_inode_header));\
+	SQUASHFS_SWAP((s)->rdev, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header));\
+	SQUASHFS_SWAP((s)->symlink_size, d, 32, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header));\
+	SQUASHFS_SWAP((s)->mtime, d, 32, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 64, 32);\
+	SQUASHFS_SWAP((s)->fragment, d, 96, 32);\
+	SQUASHFS_SWAP((s)->offset, d, 128, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 160, SQUASHFS_MAX_FILE_SIZE_LOG);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header));\
+	SQUASHFS_SWAP((s)->file_size, d, 32, 19);\
+	SQUASHFS_SWAP((s)->offset, d, 51, 13);\
+	SQUASHFS_SWAP((s)->mtime, d, 64, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 96, 24);\
+}
+
+#define SQUASHFS_SWAP_DIR_HEADER(s, d) {\
+	SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_header));\
+	SQUASHFS_SWAP((s)->count, d, 0, 8);\
+	SQUASHFS_SWAP((s)->start_block, d, 8, 24);\
+}
+
+#define SQUASHFS_SWAP_DIR_ENTRY(s, d) {\
+	SQUASHFS_MEMSET(s, d, sizeof(squashfs_dir_entry));\
+	SQUASHFS_SWAP((s)->offset, d, 0, 13);\
+	SQUASHFS_SWAP((s)->type, d, 13, 3);\
+	SQUASHFS_SWAP((s)->size, d, 16, 8);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_ENTRY(s, d) {\
+	SQUASHFS_MEMSET(s, d, sizeof(squashfs_fragment_entry));\
+	SQUASHFS_SWAP((s)->start_block, d, 0, 32);\
+	SQUASHFS_SWAP((s)->size, d, 32, 32);\
+}
+
+#define SQUASHFS_SWAP_SHORTS(s, d, n) {\
+	int entry;\
+	int bit_position;\
+	SQUASHFS_MEMSET(s, d, n * 2);\
+	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 16)\
+		SQUASHFS_SWAP(s[entry], d, bit_position, 16);\
+}
+
+#define SQUASHFS_SWAP_INTS(s, d, n) {\
+	int entry;\
+	int bit_position;\
+	SQUASHFS_MEMSET(s, d, n * 4);\
+	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += 32)\
+		SQUASHFS_SWAP(s[entry], d, bit_position, 32);\
+}
+
+#define SQUASHFS_SWAP_DATA(s, d, n, bits) {\
+	int entry;\
+	int bit_position;\
+	SQUASHFS_MEMSET(s, d, n * bits / 8);\
+	for(entry = 0, bit_position = 0; entry < n; entry++, bit_position += bits)\
+		SQUASHFS_SWAP(s[entry], d, bit_position, bits);\
+}
+
+#define SQUASHFS_SWAP_FRAGMENT_INDEXES(s, d, n) SQUASHFS_SWAP_INTS(s, d, n)
+
+#ifdef SQUASHFS_1_0_COMPATIBILITY
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+} __attribute__ ((packed)) squashfs_base_inode_header_1;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned int		type:4;
+	unsigned int		offset:4;
+} __attribute__ ((packed)) squashfs_ipc_inode_header_1;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned short		rdev;
+} __attribute__ ((packed)) squashfs_dev_inode_header_1;
+	
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned short		symlink_size;
+	char			symlink[0];
+} __attribute__ ((packed)) squashfs_symlink_inode_header_1;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned int		mtime;
+	squashfs_block		start_block;
+	unsigned int		file_size:SQUASHFS_MAX_FILE_SIZE_LOG;
+	unsigned short		block_list[0];
+} __attribute__ ((packed)) squashfs_reg_inode_header_1;
+
+typedef struct {
+	unsigned int		inode_type:4;
+	unsigned int		mode:12; /* protection */
+	unsigned int		uid:4; /* index into uid table */
+	unsigned int		guid:4; /* index into guid table */
+	unsigned int		file_size:19;
+	unsigned int		offset:13;
+	unsigned int		mtime;
+	unsigned int		start_block:24;
+} __attribute__  ((packed)) squashfs_dir_inode_header_1;
+
+#define SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, n) {\
+	SQUASHFS_MEMSET(s, d, n);\
+	SQUASHFS_SWAP((s)->inode_type, d, 0, 4);\
+	SQUASHFS_SWAP((s)->mode, d, 4, 12);\
+	SQUASHFS_SWAP((s)->uid, d, 16, 4);\
+	SQUASHFS_SWAP((s)->guid, d, 20, 4);\
+}
+
+#define SQUASHFS_SWAP_IPC_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_ipc_inode_header_1));\
+	SQUASHFS_SWAP((s)->type, d, 24, 4);\
+	SQUASHFS_SWAP((s)->offset, d, 28, 4);\
+}
+
+#define SQUASHFS_SWAP_DEV_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER_1(s, d, sizeof(squashfs_dev_inode_header_1));\
+	SQUASHFS_SWAP((s)->rdev, d, 24, 16);\
+}
+
+#define SQUASHFS_SWAP_SYMLINK_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_symlink_inode_header_1));\
+	SQUASHFS_SWAP((s)->symlink_size, d, 24, 16);\
+}
+
+#define SQUASHFS_SWAP_REG_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_reg_inode_header_1));\
+	SQUASHFS_SWAP((s)->mtime, d, 24, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 56, 32);\
+	SQUASHFS_SWAP((s)->file_size, d, 88, SQUASHFS_MAX_FILE_SIZE_LOG);\
+}
+
+#define SQUASHFS_SWAP_DIR_INODE_HEADER_1(s, d) {\
+	SQUASHFS_SWAP_BASE_INODE_HEADER(s, d, sizeof(squashfs_dir_inode_header_1));\
+	SQUASHFS_SWAP((s)->file_size, d, 24, 19);\
+	SQUASHFS_SWAP((s)->offset, d, 43, 13);\
+	SQUASHFS_SWAP((s)->mtime, d, 56, 32);\
+	SQUASHFS_SWAP((s)->start_block, d, 88, 24);\
+}
+#endif
+
+#ifdef __KERNEL__
+/*
+ * macros used to swap each structure entry, taking into account
+ * bitfields and different bitfield placing conventions on differing architectures
+ */
+#include <asm/byteorder.h>
+#ifdef __BIG_ENDIAN
+	/* convert from little endian to big endian */
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, b_pos)
+#else
+	/* convert from big endian to little endian */ 
+#define SQUASHFS_SWAP(value, p, pos, tbits) _SQUASHFS_SWAP(value, p, pos, tbits, 64 - tbits - b_pos)
+#endif
+
+#define _SQUASHFS_SWAP(value, p, pos, tbits, SHIFT) {\
+	int bits;\
+	int b_pos = pos % 8;\
+	unsigned long long val = 0;\
+	unsigned char *s = (unsigned char *)p + (pos / 8);\
+	unsigned char *d = ((unsigned char *) &val) + 7;\
+	for(bits = 0; bits < (tbits + b_pos); bits += 8) \
+		*d-- = *s++;\
+	value = (val >> (SHIFT))/* & ((1 << tbits) - 1)*/;\
+}
+#define SQUASHFS_MEMSET(s, d, n)	memset(s, 0, n);
+#endif
+#endif
diff -Nur linux-2.6.17.6/include/linux/squashfs_fs_i.h linux-2.6.17.6-bcm_squashfs/include/linux/squashfs_fs_i.h
--- linux-2.6.17.6/include/linux/squashfs_fs_i.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/include/linux/squashfs_fs_i.h	2005-04-29 03:43:56.000000000 +0200
@@ -0,0 +1,34 @@
+#ifndef SQUASHFS_FS_I
+#define SQUASHFS_FS_I
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ *
+ * 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,
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs_i.h
+ */
+
+typedef struct squashfs_inode_info {
+	unsigned int	start_block;
+	unsigned int	block_list_start;
+	unsigned int	offset;
+	unsigned int	fragment_start_block;
+	unsigned int	fragment_size;
+	unsigned int	fragment_offset;
+	struct inode	vfs_inode;
+	} squashfs_inode_info;
+#endif
diff -Nur linux-2.6.17.6/include/linux/squashfs_fs_sb.h linux-2.6.17.6-bcm_squashfs/include/linux/squashfs_fs_sb.h
--- linux-2.6.17.6/include/linux/squashfs_fs_sb.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.17.6-bcm_squashfs/include/linux/squashfs_fs_sb.h	2005-04-29 03:43:56.000000000 +0200
@@ -0,0 +1,65 @@
+#ifndef SQUASHFS_FS_SB
+#define SQUASHFS_FS_SB
+/*
+ * Squashfs
+ *
+ * Copyright (c) 2002, 2003, 2004 Phillip Lougher <plougher@users.sourceforge.net>
+ *
+ * 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,
+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * squashfs_fs_sb.h
+ */
+
+#include <linux/squashfs_fs.h>
+
+typedef struct {
+	unsigned int	block;
+	int		length;
+	unsigned int	next_index;
+	char		*data;
+	} squashfs_cache;
+
+struct squashfs_fragment_cache {
+	unsigned int	block;
+	int		length;
+	unsigned int	locked;
+	char		*data;
+	};
+
+typedef struct squashfs_sb_info {
+	squashfs_super_block	sBlk;
+	int			devblksize;
+	int			devblksize_log2;
+	int			swap;
+	squashfs_cache		*block_cache;
+	struct squashfs_fragment_cache	*fragment;
+	int			next_cache;
+	int			next_fragment;
+	squashfs_uid		*uid;
+	squashfs_uid		*guid;
+	squashfs_fragment_index		*fragment_index;
+	unsigned int		read_size;
+	char			*read_data;
+	char			*read_page;
+	struct semaphore	read_page_mutex;
+	struct semaphore	block_cache_mutex;
+	struct semaphore	fragment_mutex;
+	wait_queue_head_t	waitq;
+	wait_queue_head_t	fragment_wait_queue;
+	struct inode		*(*iget)(struct super_block *s, squashfs_inode inode);
+	unsigned int		(*read_blocklist)(struct inode *inode, int index, int readahead_blks,
+					char *block_list, char **block_p, unsigned int *bsize);
+	} squashfs_sb_info;
+#endif
diff -Nur linux-2.6.17.6/init/do_mounts_rd.c linux-2.6.17.6-bcm_squashfs/init/do_mounts_rd.c
--- linux-2.6.17.6/init/do_mounts_rd.c	2006-07-15 21:00:43.000000000 +0200
+++ linux-2.6.17.6-bcm_squashfs/init/do_mounts_rd.c	2006-09-16 09:52:49.000000000 +0200
@@ -5,6 +5,7 @@
 #include <linux/ext2_fs.h>
 #include <linux/romfs_fs.h>
 #include <linux/cramfs_fs.h>
+#include <linux/squashfs_fs.h>
 #include <linux/initrd.h>
 #include <linux/string.h>
 
@@ -39,6 +40,7 @@
  * numbers could not be found.
  *
  * We currently check for the following magic numbers:
+ *      squashfs
  * 	minix
  * 	ext2
  *	romfs
@@ -53,6 +55,7 @@
 	struct ext2_super_block *ext2sb;
 	struct romfs_super_block *romfsb;
 	struct cramfs_super *cramfsb;
+	struct squashfs_super_block *squashfsb;
 	int nblocks = -1;
 	unsigned char *buf;
 
@@ -64,6 +67,7 @@
 	ext2sb = (struct ext2_super_block *) buf;
 	romfsb = (struct romfs_super_block *) buf;
 	cramfsb = (struct cramfs_super *) buf;
+	squashfsb = (struct squashfs_super_block *) buf;
 	memset(buf, 0xe5, size);
 
 	/*
@@ -101,6 +105,18 @@
 		goto done;
 	}
 
+	/* squashfs is at block zero too */
+	if (squashfsb->s_magic == SQUASHFS_MAGIC) {
+		printk(KERN_NOTICE
+		       "RAMDISK: squashfs filesystem found at block %d\n",
+		       start_block);
+		if (squashfsb->s_major < 3)
+			nblocks = (squashfsb->bytes_used_2+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
+		else
+			nblocks = (squashfsb->bytes_used+BLOCK_SIZE-1)>>BLOCK_SIZE_BITS;
+		goto done;
+	}
+
 	/*
 	 * Read block 1 to test for minix and ext2 superblock
 	 */
