From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001
From: James <>
Date: Wed, 4 Nov 2015 11:49:21 +0000
Subject: trunk-47381

---
 target/linux/generic/image/lzma-loader/Makefile    |  46 ++
 .../generic/image/lzma-loader/src/LzmaDecode.c     | 590 +++++++++++++++++++++
 .../generic/image/lzma-loader/src/LzmaDecode.h     | 131 +++++
 .../linux/generic/image/lzma-loader/src/Makefile   |  68 +++
 .../generic/image/lzma-loader/src/decompress.c     | 157 ++++++
 .../generic/image/lzma-loader/src/lzma-copy.lds.in |  20 +
 .../generic/image/lzma-loader/src/lzma.lds.in      |  24 +
 target/linux/generic/image/lzma-loader/src/print.c | 324 +++++++++++
 target/linux/generic/image/lzma-loader/src/print.h |  36 ++
 .../linux/generic/image/lzma-loader/src/printf.c   |  35 ++
 .../linux/generic/image/lzma-loader/src/printf.h   |  18 +
 target/linux/generic/image/lzma-loader/src/start.S | 160 ++++++
 .../generic/image/lzma-loader/src/uart16550.c      |  86 +++
 .../generic/image/lzma-loader/src/uart16550.h      |  47 ++
 14 files changed, 1742 insertions(+)
 create mode 100644 target/linux/generic/image/lzma-loader/Makefile
 create mode 100644 target/linux/generic/image/lzma-loader/src/LzmaDecode.c
 create mode 100644 target/linux/generic/image/lzma-loader/src/LzmaDecode.h
 create mode 100644 target/linux/generic/image/lzma-loader/src/Makefile
 create mode 100644 target/linux/generic/image/lzma-loader/src/decompress.c
 create mode 100644 target/linux/generic/image/lzma-loader/src/lzma-copy.lds.in
 create mode 100644 target/linux/generic/image/lzma-loader/src/lzma.lds.in
 create mode 100644 target/linux/generic/image/lzma-loader/src/print.c
 create mode 100644 target/linux/generic/image/lzma-loader/src/print.h
 create mode 100644 target/linux/generic/image/lzma-loader/src/printf.c
 create mode 100644 target/linux/generic/image/lzma-loader/src/printf.h
 create mode 100644 target/linux/generic/image/lzma-loader/src/start.S
 create mode 100644 target/linux/generic/image/lzma-loader/src/uart16550.c
 create mode 100644 target/linux/generic/image/lzma-loader/src/uart16550.h

(limited to 'target/linux/generic/image/lzma-loader')

diff --git a/target/linux/generic/image/lzma-loader/Makefile b/target/linux/generic/image/lzma-loader/Makefile
new file mode 100644
index 0000000..d75a446
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/Makefile
@@ -0,0 +1,46 @@
+# 
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME := loader
+PKG_VERSION := 0.05
+
+PKG_BUILD_DIR := $(KDIR)/$(PKG_NAME)-$(PKG_VERSION)$(LOADER_TYPE)
+
+$(PKG_BUILD_DIR)/.prepared:
+	mkdir $(PKG_BUILD_DIR)
+	$(CP) ./src/* $(PKG_BUILD_DIR)/
+	touch $@
+
+$(PKG_BUILD_DIR)/lzma.elf: $(PKG_BUILD_DIR)/.prepared $(PKG_BUILD_DIR)/vmlinux.lzma
+	PATH="$(TARGET_PATH)" $(MAKE) -C $(PKG_BUILD_DIR) \
+		CC="$(TARGET_CC)" CROSS_COMPILE="$(TARGET_CROSS)" \
+		RAMSIZE=$(RAMSIZE) \
+		LOADADDR=$(LOADADDR) \
+		KERNEL_ENTRY=$(KERNEL_ENTRY) \
+		IMAGE_COPY=$(IMAGE_COPY)
+
+
+$(PKG_BUILD_DIR)/vmlinux.lzma: $(KDIR)/vmlinux.lzma
+	$(CP) $< $@
+
+$(KDIR)/loader$(LOADER_TYPE).elf: $(PKG_BUILD_DIR)/lzma.elf
+	$(CP) $< $@
+
+$(KDIR)/loader$(LOADER_TYPE).bin: $(PKG_BUILD_DIR)/lzma.bin
+	$(CP) $< $@
+
+download: 
+prepare: $(PKG_BUILD_DIR)/.prepared
+compile: $(KDIR)/loader$(LOADER_TYPE).elf $(KDIR)/loader$(LOADER_TYPE).bin
+install:
+
+clean:
+	rm -rf $(PKG_BUILD_DIR)
+	rm -f $(KDIR)/loader.elf
+	rm -f $(KDIR)/loader.bin
diff --git a/target/linux/generic/image/lzma-loader/src/LzmaDecode.c b/target/linux/generic/image/lzma-loader/src/LzmaDecode.c
new file mode 100644
index 0000000..c90a0d3
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/LzmaDecode.c
@@ -0,0 +1,590 @@
+/*
+  LzmaDecode.c
+  LZMA Decoder (optimized for Speed version)
+  
+  LZMA SDK 4.22 Copyright (c) 1999-2005 Igor Pavlov (2005-06-10)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and 
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this Code, expressly permits you to 
+  statically or dynamically link your Code (or bind by name) to the 
+  interfaces of this file without subjecting your linked Code to the 
+  terms of the CPL or GNU LGPL. Any modifications or additions 
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#include "LzmaDecode.h"
+
+#ifndef Byte
+#define Byte unsigned char
+#endif
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_READ_BYTE (*Buffer++)
+
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
+
+#ifdef _LZMA_IN_CB
+
+#define RC_TEST { if (Buffer == BufferLim) \
+  { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+  BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
+
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
+
+#else
+
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
+
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+ 
+#endif
+
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
+
+#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
+#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
+#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
+
+#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
+  { UpdateBit0(p); mi <<= 1; A0; } else \
+  { UpdateBit1(p); mi = (mi + mi) + 1; A1; } 
+  
+#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               
+
+#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
+  { int i = numLevels; res = 1; \
+  do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
+  res -= (1 << numLevels); }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+#if 0
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
+{
+  unsigned char prop0;
+  if (size < LZMA_PROPERTIES_SIZE)
+    return LZMA_RESULT_DATA_ERROR;
+  prop0 = propsData[0];
+  if (prop0 >= (9 * 5 * 5))
+    return LZMA_RESULT_DATA_ERROR;
+  {
+    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+    propsRes->lc = prop0;
+    /*
+    unsigned char remainder = (unsigned char)(prop0 / 9);
+    propsRes->lc = prop0 % 9;
+    propsRes->pb = remainder / 5;
+    propsRes->lp = remainder % 5;
+    */
+  }
+
+  #ifdef _LZMA_OUT_READ
+  {
+    int i;
+    propsRes->DictionarySize = 0;
+    for (i = 0; i < 4; i++)
+      propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+    if (propsRes->DictionarySize == 0)
+      propsRes->DictionarySize = 1;
+  }
+  #endif
+  return LZMA_RESULT_OK;
+}
+#endif
+
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+    #ifdef _LZMA_IN_CB
+    ILzmaInCallback *InCallback,
+    #else
+    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+    #endif
+    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
+{
+  CProb *p = vs->Probs;
+  SizeT nowPos = 0;
+  Byte previousByte = 0;
+  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+  int lc = vs->Properties.lc;
+
+  #ifdef _LZMA_OUT_READ
+  
+  UInt32 Range = vs->Range;
+  UInt32 Code = vs->Code;
+  #ifdef _LZMA_IN_CB
+  const Byte *Buffer = vs->Buffer;
+  const Byte *BufferLim = vs->BufferLim;
+  #else
+  const Byte *Buffer = inStream;
+  const Byte *BufferLim = inStream + inSize;
+  #endif
+  int state = vs->State;
+  UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
+  int len = vs->RemainLen;
+  UInt32 globalPos = vs->GlobalPos;
+  UInt32 distanceLimit = vs->DistanceLimit;
+
+  Byte *dictionary = vs->Dictionary;
+  UInt32 dictionarySize = vs->Properties.DictionarySize;
+  UInt32 dictionaryPos = vs->DictionaryPos;
+
+  Byte tempDictionary[4];
+
+  #ifndef _LZMA_IN_CB
+  *inSizeProcessed = 0;
+  #endif
+  *outSizeProcessed = 0;
+  if (len == kLzmaStreamWasFinishedId)
+    return LZMA_RESULT_OK;
+
+  if (dictionarySize == 0)
+  {
+    dictionary = tempDictionary;
+    dictionarySize = 1;
+    tempDictionary[0] = vs->TempDictionary[0];
+  }
+
+  if (len == kLzmaNeedInitId)
+  {
+    {
+      UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+      UInt32 i;
+      for (i = 0; i < numProbs; i++)
+        p[i] = kBitModelTotal >> 1; 
+      rep0 = rep1 = rep2 = rep3 = 1;
+      state = 0;
+      globalPos = 0;
+      distanceLimit = 0;
+      dictionaryPos = 0;
+      dictionary[dictionarySize - 1] = 0;
+      #ifdef _LZMA_IN_CB
+      RC_INIT;
+      #else
+      RC_INIT(inStream, inSize);
+      #endif
+    }
+    len = 0;
+  }
+  while(len != 0 && nowPos < outSize)
+  {
+    UInt32 pos = dictionaryPos - rep0;
+    if (pos >= dictionarySize)
+      pos += dictionarySize;
+    outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
+    if (++dictionaryPos == dictionarySize)
+      dictionaryPos = 0;
+    len--;
+  }
+  if (dictionaryPos == 0)
+    previousByte = dictionary[dictionarySize - 1];
+  else
+    previousByte = dictionary[dictionaryPos - 1];
+
+  #else /* if !_LZMA_OUT_READ */
+
+  int state = 0;
+  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
+  int len = 0;
+  const Byte *Buffer;
+  const Byte *BufferLim;
+  UInt32 Range;
+  UInt32 Code;
+
+  #ifndef _LZMA_IN_CB
+  *inSizeProcessed = 0;
+  #endif
+  *outSizeProcessed = 0;
+
+  {
+    UInt32 i;
+    UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+    for (i = 0; i < numProbs; i++)
+      p[i] = kBitModelTotal >> 1;
+  }
+  
+  #ifdef _LZMA_IN_CB
+  RC_INIT;
+  #else
+  RC_INIT(inStream, inSize);
+  #endif
+
+  #endif /* _LZMA_OUT_READ */
+
+  while(nowPos < outSize)
+  {
+    CProb *prob;
+    UInt32 bound;
+    int posState = (int)(
+        (nowPos 
+        #ifdef _LZMA_OUT_READ
+        + globalPos
+        #endif
+        )
+        & posStateMask);
+
+    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+    IfBit0(prob)
+    {
+      int symbol = 1;
+      UpdateBit0(prob)
+      prob = p + Literal + (LZMA_LIT_SIZE * 
+        (((
+        (nowPos 
+        #ifdef _LZMA_OUT_READ
+        + globalPos
+        #endif
+        )
+        & literalPosMask) << lc) + (previousByte >> (8 - lc))));
+
+      if (state >= kNumLitStates)
+      {
+        int matchByte;
+        #ifdef _LZMA_OUT_READ
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        matchByte = dictionary[pos];
+        #else
+        matchByte = outStream[nowPos - rep0];
+        #endif
+        do
+        {
+          int bit;
+          CProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & 0x100);
+          probLit = prob + 0x100 + bit + symbol;
+          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
+        }
+        while (symbol < 0x100);
+      }
+      while (symbol < 0x100)
+      {
+        CProb *probLit = prob + symbol;
+        RC_GET_BIT(probLit, symbol)
+      }
+      previousByte = (Byte)symbol;
+
+      outStream[nowPos++] = previousByte;
+      #ifdef _LZMA_OUT_READ
+      if (distanceLimit < dictionarySize)
+        distanceLimit++;
+
+      dictionary[dictionaryPos] = previousByte;
+      if (++dictionaryPos == dictionarySize)
+        dictionaryPos = 0;
+      #endif
+      if (state < 4) state = 0;
+      else if (state < 10) state -= 3;
+      else state -= 6;
+    }
+    else             
+    {
+      UpdateBit1(prob);
+      prob = p + IsRep + state;
+      IfBit0(prob)
+      {
+        UpdateBit0(prob);
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        state = state < kNumLitStates ? 0 : 3;
+        prob = p + LenCoder;
+      }
+      else
+      {
+        UpdateBit1(prob);
+        prob = p + IsRepG0 + state;
+        IfBit0(prob)
+        {
+          UpdateBit0(prob);
+          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IfBit0(prob)
+          {
+            #ifdef _LZMA_OUT_READ
+            UInt32 pos;
+            #endif
+            UpdateBit0(prob);
+            
+            #ifdef _LZMA_OUT_READ
+            if (distanceLimit == 0)
+            #else
+            if (nowPos == 0)
+            #endif
+              return LZMA_RESULT_DATA_ERROR;
+            
+            state = state < kNumLitStates ? 9 : 11;
+            #ifdef _LZMA_OUT_READ
+            pos = dictionaryPos - rep0;
+            if (pos >= dictionarySize)
+              pos += dictionarySize;
+            previousByte = dictionary[pos];
+            dictionary[dictionaryPos] = previousByte;
+            if (++dictionaryPos == dictionarySize)
+              dictionaryPos = 0;
+            #else
+            previousByte = outStream[nowPos - rep0];
+            #endif
+            outStream[nowPos++] = previousByte;
+            #ifdef _LZMA_OUT_READ
+            if (distanceLimit < dictionarySize)
+              distanceLimit++;
+            #endif
+
+            continue;
+          }
+          else
+          {
+            UpdateBit1(prob);
+          }
+        }
+        else
+        {
+          UInt32 distance;
+          UpdateBit1(prob);
+          prob = p + IsRepG1 + state;
+          IfBit0(prob)
+          {
+            UpdateBit0(prob);
+            distance = rep1;
+          }
+          else 
+          {
+            UpdateBit1(prob);
+            prob = p + IsRepG2 + state;
+            IfBit0(prob)
+            {
+              UpdateBit0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UpdateBit1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state < kNumLitStates ? 8 : 11;
+        prob = p + RepLenCoder;
+      }
+      {
+        int numBits, offset;
+        CProb *probLen = prob + LenChoice;
+        IfBit0(probLen)
+        {
+          UpdateBit0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          numBits = kLenNumLowBits;
+        }
+        else
+        {
+          UpdateBit1(probLen);
+          probLen = prob + LenChoice2;
+          IfBit0(probLen)
+          {
+            UpdateBit0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            numBits = kLenNumMidBits;
+          }
+          else
+          {
+            UpdateBit1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            numBits = kLenNumHighBits;
+          }
+        }
+        RangeDecoderBitTreeDecode(probLen, numBits, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        int posSlot;
+        state += kNumLitStates;
+        prob = p + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
+            kNumPosSlotBits);
+        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+          rep0 = (2 | ((UInt32)posSlot & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            rep0 <<= numDirectBits;
+            prob = p + SpecPos + rep0 - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              RC_NORMALIZE
+              Range >>= 1;
+              rep0 <<= 1;
+              if (Code >= Range)
+              {
+                Code -= Range;
+                rep0 |= 1;
+              }
+            }
+            while (--numDirectBits != 0);
+            prob = p + Align;
+            rep0 <<= kNumAlignBits;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            int i = 1;
+            int mi = 1;
+            do
+            {
+              CProb *prob3 = prob + mi;
+              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
+              i <<= 1;
+            }
+            while(--numDirectBits != 0);
+          }
+        }
+        else
+          rep0 = posSlot;
+        if (++rep0 == (UInt32)(0))
+        {
+          /* it's for stream version */
+          len = kLzmaStreamWasFinishedId;
+          break;
+        }
+      }
+
+      len += kMatchMinLen;
+      #ifdef _LZMA_OUT_READ
+      if (rep0 > distanceLimit) 
+      #else
+      if (rep0 > nowPos)
+      #endif
+        return LZMA_RESULT_DATA_ERROR;
+
+      #ifdef _LZMA_OUT_READ
+      if (dictionarySize - distanceLimit > (UInt32)len)
+        distanceLimit += len;
+      else
+        distanceLimit = dictionarySize;
+      #endif
+
+      do
+      {
+        #ifdef _LZMA_OUT_READ
+        UInt32 pos = dictionaryPos - rep0;
+        if (pos >= dictionarySize)
+          pos += dictionarySize;
+        previousByte = dictionary[pos];
+        dictionary[dictionaryPos] = previousByte;
+        if (++dictionaryPos == dictionarySize)
+          dictionaryPos = 0;
+        #else
+        previousByte = outStream[nowPos - rep0];
+        #endif
+        len--;
+        outStream[nowPos++] = previousByte;
+      }
+      while(len != 0 && nowPos < outSize);
+    }
+  }
+  RC_NORMALIZE;
+
+  #ifdef _LZMA_OUT_READ
+  vs->Range = Range;
+  vs->Code = Code;
+  vs->DictionaryPos = dictionaryPos;
+  vs->GlobalPos = globalPos + (UInt32)nowPos;
+  vs->DistanceLimit = distanceLimit;
+  vs->Reps[0] = rep0;
+  vs->Reps[1] = rep1;
+  vs->Reps[2] = rep2;
+  vs->Reps[3] = rep3;
+  vs->State = state;
+  vs->RemainLen = len;
+  vs->TempDictionary[0] = tempDictionary[0];
+  #endif
+
+  #ifdef _LZMA_IN_CB
+  vs->Buffer = Buffer;
+  vs->BufferLim = BufferLim;
+  #else
+  *inSizeProcessed = (SizeT)(Buffer - inStream);
+  #endif
+  *outSizeProcessed = nowPos;
+  return LZMA_RESULT_OK;
+}
diff --git a/target/linux/generic/image/lzma-loader/src/LzmaDecode.h b/target/linux/generic/image/lzma-loader/src/LzmaDecode.h
new file mode 100644
index 0000000..213062a
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/LzmaDecode.h
@@ -0,0 +1,131 @@
+/* 
+  LzmaDecode.h
+  LZMA Decoder interface
+
+  LZMA SDK 4.21 Copyright (c) 1999-2005 Igor Pavlov (2005-06-08)
+  http://www.7-zip.org/
+
+  LZMA SDK is licensed under two licenses:
+  1) GNU Lesser General Public License (GNU LGPL)
+  2) Common Public License (CPL)
+  It means that you can select one of these two licenses and 
+  follow rules of that license.
+
+  SPECIAL EXCEPTION:
+  Igor Pavlov, as the author of this code, expressly permits you to 
+  statically or dynamically link your code (or bind by name) to the 
+  interfaces of this file without subjecting your linked code to the 
+  terms of the CPL or GNU LGPL. Any modifications or additions 
+  to this file, however, are subject to the LGPL or CPL terms.
+*/
+
+#ifndef __LZMADECODE_H
+#define __LZMADECODE_H
+
+/* #define _LZMA_IN_CB */
+/* Use callback for input data */
+
+/* #define _LZMA_OUT_READ */
+/* Use read function for output data */
+
+/* #define _LZMA_PROB32 */
+/* It can increase speed on some 32-bit CPUs, 
+   but memory usage will be doubled in that case */
+
+/* #define _LZMA_LOC_OPT */
+/* Enable local speed optimizations inside code */
+
+/* #define _LZMA_SYSTEM_SIZE_T */
+/* Use system's size_t. You can use it to enable 64-bit sizes supporting*/
+
+#ifndef UInt32
+#ifdef _LZMA_UINT32_IS_ULONG
+#define UInt32 unsigned long
+#else
+#define UInt32 unsigned int
+#endif
+#endif
+
+#ifndef SizeT
+#ifdef _LZMA_SYSTEM_SIZE_T
+#include <stddef.h>
+#define SizeT size_t
+#else
+#define SizeT UInt32
+#endif
+#endif
+
+#ifdef _LZMA_PROB32
+#define CProb UInt32
+#else
+#define CProb unsigned short
+#endif
+
+#define LZMA_RESULT_OK 0
+#define LZMA_RESULT_DATA_ERROR 1
+
+#ifdef _LZMA_IN_CB
+typedef struct _ILzmaInCallback
+{
+  int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
+} ILzmaInCallback;
+#endif
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LZMA_PROPERTIES_SIZE 5
+
+typedef struct _CLzmaProperties
+{
+  int lc;
+  int lp;
+  int pb;
+  #ifdef _LZMA_OUT_READ
+  UInt32 DictionarySize;
+  #endif
+}CLzmaProperties;
+
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
+
+#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
+
+#define kLzmaNeedInitId (-2)
+
+typedef struct _CLzmaDecoderState
+{
+  CLzmaProperties Properties;
+  CProb *Probs;
+
+  #ifdef _LZMA_IN_CB
+  const unsigned char *Buffer;
+  const unsigned char *BufferLim;
+  #endif
+
+  #ifdef _LZMA_OUT_READ
+  unsigned char *Dictionary;
+  UInt32 Range;
+  UInt32 Code;
+  UInt32 DictionaryPos;
+  UInt32 GlobalPos;
+  UInt32 DistanceLimit;
+  UInt32 Reps[4];
+  int State;
+  int RemainLen;
+  unsigned char TempDictionary[4];
+  #endif
+} CLzmaDecoderState;
+
+#ifdef _LZMA_OUT_READ
+#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
+#endif
+
+int LzmaDecode(CLzmaDecoderState *vs,
+    #ifdef _LZMA_IN_CB
+    ILzmaInCallback *inCallback,
+    #else
+    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+    #endif
+    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
+
+#endif
diff --git a/target/linux/generic/image/lzma-loader/src/Makefile b/target/linux/generic/image/lzma-loader/src/Makefile
new file mode 100644
index 0000000..910172c
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/Makefile
@@ -0,0 +1,68 @@
+# 
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+RAMSTART = 0x80000000
+RAMSIZE = 0x00100000		# 1MB
+LOADADDR = 0x80400000		# RAM start + 4M
+KERNEL_ENTRY = 0x80001000
+IMAGE_COPY:=0
+
+CROSS_COMPILE = mips-linux-
+
+OBJCOPY:= $(CROSS_COMPILE)objcopy -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
+CFLAGS := -fno-builtin -Os -G 0 -ffunction-sections -mno-abicalls -fno-pic -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -Wall -DRAMSTART=${RAMSTART} -DRAMSIZE=${RAMSIZE} -DKERNEL_ENTRY=${KERNEL_ENTRY} -D_LZMA_IN_CB
+ifeq ($(IMAGE_COPY),1)
+CFLAGS += -DLOADADDR=${LOADADDR} -DIMAGE_COPY=1
+endif
+
+.S.s:
+	$(CPP) $(CFLAGS) $< -o $*.s
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+.c.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+CC =       $(CROSS_COMPILE)gcc
+LD =       $(CROSS_COMPILE)ld
+OBJDUMP =  $(CROSS_COMPILE)objdump
+
+O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
+
+# Drop some uninteresting sections in the kernel.
+# This is only relevant for ELF kernels but doesn't hurt a.out
+drop-sections   = .reginfo .mdebug .comment
+strip-flags     = $(addprefix --remove-section=,$(drop-sections))
+
+all : lzma.elf lzma.bin
+
+lzma.lds: lzma.lds.in
+	sed -e 's,@LOADADDR@,$(LOADADDR),g' -e 's,@ENTRY@,_start,g' $< >$@
+
+kernel.o: vmlinux.lzma lzma.lds
+	$(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $<
+
+lzma.bin: lzma.elf
+	$(OBJCOPY) $< $@
+
+ifeq ($(IMAGE_COPY),1)
+LOADER_ENTRY ?= $(KERNEL_ENTRY)
+lzma.o: decompress.o LzmaDecode.o kernel.o
+	sed -e 's,@LOADADDR@,$(LOADADDR),g' -e 's,@ENTRY@,entry,g' lzma.lds.in >lzma-stage2.lds
+	$(LD) -static --no-warn-mismatch -e entry -Tlzma-stage2.lds -o temp-$@ $^
+	$(OBJCOPY) temp-$@ lzma.tmp
+	@echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > lzma-data.lds
+	$(LD) -no-warn-mismatch -T lzma-data.lds -r -o $@ -b binary lzma.tmp --oformat $(O_FORMAT)
+	
+lzma.elf: start.o lzma.o
+	sed -e 's,@LOADADDR@,$(LOADER_ENTRY),g' lzma-copy.lds.in >lzma-copy.lds
+	$(LD) -s -Tlzma-copy.lds -o $@ $^
+else
+lzma.elf: start.o decompress.o LzmaDecode.o kernel.o
+	$(LD) -s -Tlzma.lds -o $@ $^
+endif
+
+clean:
+	rm -f *.o lzma.elf lzma.bin *.tmp *.lds
diff --git a/target/linux/generic/image/lzma-loader/src/decompress.c b/target/linux/generic/image/lzma-loader/src/decompress.c
new file mode 100644
index 0000000..45ac509
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/decompress.c
@@ -0,0 +1,157 @@
+/*
+ * LZMA compressed kernel decompressor for bcm947xx boards
+ *
+ * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * Please note, this was code based on the bunzip2 decompressor code
+ * by Manuel Novoa III  (mjn3@codepoet.org), although the only thing left
+ * is an idea and part of original vendor code
+ *
+ *
+ * 12-Mar-2005  Mineharu Takahara <mtakahar@yahoo.com>
+ *   pass actual output size to decoder (stream mode
+ *   compressed input is not a requirement anymore)
+ *
+ * 24-Apr-2005 Oleg I. Vdovikin
+ *   reordered functions using lds script, removed forward decl
+ *
+ * ??-Nov-2005 Mike Baker
+ *   reorder the script as an lzma wrapper; do not depend on flash access
+ */
+
+#include "LzmaDecode.h"
+
+#define KSEG0			0x80000000
+#define KSEG1			0xa0000000
+
+#define KSEG1ADDR(a)		((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
+
+#define Index_Invalidate_I	0x00
+#define Index_Writeback_Inv_D   0x01
+
+#define cache_unroll(base,op)	\
+	__asm__ __volatile__(		\
+		".set noreorder;\n"		\
+		".set mips3;\n"			\
+		"cache %1, (%0);\n"		\
+		".set mips0;\n"			\
+		".set reorder\n"		\
+		:						\
+		: "r" (base),			\
+		  "i" (op));
+
+
+static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + size);
+
+	while(start < end) {
+		cache_unroll(start,Index_Invalidate_I);
+		start += lsize;
+	}
+}
+
+static __inline__ void blast_dcache(unsigned long size, unsigned long lsize)
+{
+	unsigned long start = KSEG0;
+	unsigned long end = (start + size);
+
+	while(start < end) {
+		cache_unroll(start,Index_Writeback_Inv_D);
+		start += lsize;
+	}
+}
+
+unsigned char *data;
+
+static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
+{
+	*bufferSize = 1;
+	*buffer = data;
+	++data;
+	return LZMA_RESULT_OK;
+}
+
+static __inline__ unsigned char get_byte(void)
+{
+	unsigned char *buffer;
+	UInt32 fake;
+	
+	return read_byte(0, &buffer, &fake), *buffer;
+}
+
+/* This puts lzma workspace 128k below RAM end. 
+ * That should be enough for both lzma and stack
+ */
+static char *buffer = (char *)(RAMSTART + RAMSIZE - 0x00020000);
+extern char lzma_start[];
+extern char lzma_end[];
+
+/* should be the first function */
+void entry(unsigned long icache_size, unsigned long icache_lsize, 
+	unsigned long dcache_size, unsigned long dcache_lsize)
+{
+	unsigned int i;  /* temp value */
+	unsigned int osize; /* uncompressed size */
+	volatile unsigned int arg0, arg1, arg2, arg3;
+
+	/* restore argument registers */
+	__asm__ __volatile__ ("ori %0, $12, 0":"=r"(arg0));
+	__asm__ __volatile__ ("ori %0, $13, 0":"=r"(arg1));
+	__asm__ __volatile__ ("ori %0, $14, 0":"=r"(arg2));
+	__asm__ __volatile__ ("ori %0, $15, 0":"=r"(arg3));
+
+	ILzmaInCallback callback;
+	CLzmaDecoderState vs;
+	callback.Read = read_byte;
+
+	data = lzma_start;
+
+	/* lzma args */
+	i = get_byte();
+	vs.Properties.lc = i % 9, i = i / 9;
+	vs.Properties.lp = i % 5, vs.Properties.pb = i / 5;
+
+	vs.Probs = (CProb *)buffer;
+
+	/* skip rest of the LZMA coder property */
+	for (i = 0; i < 4; i++)
+		get_byte();
+
+	/* read the lower half of uncompressed size in the header */
+	osize = ((unsigned int)get_byte()) +
+		((unsigned int)get_byte() << 8) +
+		((unsigned int)get_byte() << 16) +
+		((unsigned int)get_byte() << 24);
+
+	/* skip rest of the header (upper half of uncompressed size) */
+	for (i = 0; i < 4; i++) 
+		get_byte();
+
+	/* decompress kernel */
+	if ((i = LzmaDecode(&vs, &callback,
+	(unsigned char*)KERNEL_ENTRY, osize, &osize)) == LZMA_RESULT_OK)
+	{
+		blast_dcache(dcache_size, dcache_lsize);
+		blast_icache(icache_size, icache_lsize);
+
+		/* Jump to load address */
+		((void (*)(int a0, int a1, int a2, int a3)) KERNEL_ENTRY)(arg0, arg1, arg2, arg3);
+	}
+}
diff --git a/target/linux/generic/image/lzma-loader/src/lzma-copy.lds.in b/target/linux/generic/image/lzma-loader/src/lzma-copy.lds.in
new file mode 100644
index 0000000..fbc87ab
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/lzma-copy.lds.in
@@ -0,0 +1,20 @@
+OUTPUT_ARCH(mips)
+ENTRY(_start)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = @LOADADDR@;
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+  } =0
+
+  .reginfo : { *(.reginfo) }
+
+  .bss       :
+  {
+   *(.bss)
+  }
+}
diff --git a/target/linux/generic/image/lzma-loader/src/lzma.lds.in b/target/linux/generic/image/lzma-loader/src/lzma.lds.in
new file mode 100644
index 0000000..6021cec
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/lzma.lds.in
@@ -0,0 +1,24 @@
+OUTPUT_ARCH(mips)
+ENTRY(@ENTRY@)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = @LOADADDR@;
+  .text      :
+  {
+    _ftext = . ;
+    *(.text.entry)
+    *(.text)
+    *(.rodata)
+    lzma_start = .;
+    kernel.o
+    lzma_end = .;
+  } =0
+
+  .reginfo : { *(.reginfo) }
+
+  .bss       :
+  {
+   *(.bss)
+  }
+}
diff --git a/target/linux/generic/image/lzma-loader/src/print.c b/target/linux/generic/image/lzma-loader/src/print.c
new file mode 100644
index 0000000..950687b
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/print.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include	"print.h"
+
+/* macros */
+#define		IsDigit(x)	( ((x) >= '0') && ((x) <= '9') )
+#define		Ctod(x)		( (x) - '0')
+
+/* forward declaration */
+extern int PrintChar(char *, char, int, int);
+extern int PrintString(char *, char *, int, int);
+extern int PrintNum(char *, unsigned long, int, int, int, int, char, int);
+
+/* private variable */
+static const char theFatalMsg[] = "fatal error in lp_Print!";
+
+/* -*-
+ * A low level printf() function.
+ */
+void
+lp_Print(void (*output)(void *, char *, int), 
+	 void * arg,
+	 char *fmt, 
+	 va_list ap)
+{
+
+#define 	OUTPUT(arg, s, l)  \
+  { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \
+       (*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \
+    } else { \
+      (*output)(arg, s, l); \
+    } \
+  }
+    
+    char buf[LP_MAX_BUF];
+
+    char c;
+    char *s;
+    long int num;
+
+    int longFlag;
+    int negFlag;
+    int width;
+    int prec;
+    int ladjust;
+    char padc;
+
+    int length;
+
+    for(;;) {
+	{ 
+	    /* scan for the next '%' */
+	    char *fmtStart = fmt;
+	    while ( (*fmt != '\0') && (*fmt != '%')) {
+		fmt ++;
+	    }
+
+	    /* flush the string found so far */
+	    OUTPUT(arg, fmtStart, fmt-fmtStart);
+
+	    /* are we hitting the end? */
+	    if (*fmt == '\0') break;
+	}
+
+	/* we found a '%' */
+	fmt ++;
+	
+	/* check for long */
+	if (*fmt == 'l') {
+	    longFlag = 1;
+	    fmt ++;
+	} else {
+	    longFlag = 0;
+	}
+
+	/* check for other prefixes */
+	width = 0;
+	prec = -1;
+	ladjust = 0;
+	padc = ' ';
+
+	if (*fmt == '-') {
+	    ladjust = 1;
+	    fmt ++;
+	}
+
+	if (*fmt == '0') {
+	    padc = '0';
+	    fmt++;
+	}
+
+	if (IsDigit(*fmt)) {
+	    while (IsDigit(*fmt)) {
+		width = 10 * width + Ctod(*fmt++);
+	    }
+	}
+
+	if (*fmt == '.') {
+	    fmt ++;
+	    if (IsDigit(*fmt)) {
+		prec = 0;
+		while (IsDigit(*fmt)) {
+		    prec = prec*10 + Ctod(*fmt++);
+		}
+	    }
+	}
+
+
+	/* check format flag */
+	negFlag = 0;
+	switch (*fmt) {
+	 case 'b':
+	    if (longFlag) { 
+		num = va_arg(ap, long int); 
+	    } else { 
+		num = va_arg(ap, int);
+	    }
+	    length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0);
+	    OUTPUT(arg, buf, length);
+	    break;
+
+	 case 'd':
+	 case 'D':
+	    if (longFlag) { 
+		num = va_arg(ap, long int);
+	    } else { 
+		num = va_arg(ap, int); 
+	    }
+	    if (num < 0) {
+		num = - num;
+		negFlag = 1;
+	    }
+	    length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0);
+	    OUTPUT(arg, buf, length);
+	    break;
+
+	 case 'o':
+	 case 'O':
+	    if (longFlag) { 
+		num = va_arg(ap, long int);
+	    } else { 
+		num = va_arg(ap, int); 
+	    }
+	    length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0);
+	    OUTPUT(arg, buf, length);
+	    break;
+
+	 case 'u':
+	 case 'U':
+	    if (longFlag) { 
+		num = va_arg(ap, long int);
+	    } else { 
+		num = va_arg(ap, int); 
+	    }
+	    length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0);
+	    OUTPUT(arg, buf, length);
+	    break;
+	    
+	 case 'x':
+	    if (longFlag) { 
+		num = va_arg(ap, long int);
+	    } else { 
+		num = va_arg(ap, int); 
+	    }
+	    length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0);
+	    OUTPUT(arg, buf, length);
+	    break;
+
+	 case 'X':
+	    if (longFlag) { 
+		num = va_arg(ap, long int);
+	    } else { 
+		num = va_arg(ap, int); 
+	    }
+	    length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1);
+	    OUTPUT(arg, buf, length);
+	    break;
+
+	 case 'c':
+	    c = (char)va_arg(ap, int);
+	    length = PrintChar(buf, c, width, ladjust);
+	    OUTPUT(arg, buf, length);
+	    break;
+
+	 case 's':
+	    s = (char*)va_arg(ap, char *);
+	    length = PrintString(buf, s, width, ladjust);
+	    OUTPUT(arg, buf, length);
+	    break;
+
+	 case '\0':
+	    fmt --;
+	    break;
+
+	 default:
+	    /* output this char as it is */
+	    OUTPUT(arg, fmt, 1);
+	}	/* switch (*fmt) */
+
+	fmt ++;
+    }		/* for(;;) */
+
+    /* special termination call */
+    OUTPUT(arg, "\0", 1);
+}
+
+
+/* --------------- local help functions --------------------- */
+int
+PrintChar(char * buf, char c, int length, int ladjust)
+{
+    int i;
+    
+    if (length < 1) length = 1;
+    if (ladjust) {
+	*buf = c;
+	for (i=1; i< length; i++) buf[i] = ' ';
+    } else {
+	for (i=0; i< length-1; i++) buf[i] = ' ';
+	buf[length - 1] = c;
+    }
+    return length;
+}
+
+int
+PrintString(char * buf, char* s, int length, int ladjust)
+{
+    int i;
+    int len=0;
+    char* s1 = s;
+    while (*s1++) len++;
+    if (length < len) length = len;
+
+    if (ladjust) {
+	for (i=0; i< len; i++) buf[i] = s[i];
+	for (i=len; i< length; i++) buf[i] = ' ';
+    } else {
+	for (i=0; i< length-len; i++) buf[i] = ' ';
+	for (i=length-len; i < length; i++) buf[i] = s[i-length+len];
+    }
+    return length;
+}
+
+int
+PrintNum(char * buf, unsigned long u, int base, int negFlag, 
+	 int length, int ladjust, char padc, int upcase)
+{
+    /* algorithm :
+     *  1. prints the number from left to right in reverse form.
+     *  2. fill the remaining spaces with padc if length is longer than
+     *     the actual length
+     *     TRICKY : if left adjusted, no "0" padding.
+     *		    if negtive, insert  "0" padding between "0" and number.
+     *  3. if (!ladjust) we reverse the whole string including paddings
+     *  4. otherwise we only reverse the actual string representing the num.
+     */
+
+    int actualLength =0;
+    char *p = buf;
+    int i;
+
+    do {
+	int tmp = u %base;
+	if (tmp <= 9) {
+	    *p++ = '0' + tmp;
+	} else if (upcase) {
+	    *p++ = 'A' + tmp - 10;
+	} else {
+	    *p++ = 'a' + tmp - 10;
+	}
+	u /= base;
+    } while (u != 0);
+
+    if (negFlag) {
+	*p++ = '-';
+    }
+
+    /* figure out actual length and adjust the maximum length */
+    actualLength = p - buf;
+    if (length < actualLength) length = actualLength;
+
+    /* add padding */
+    if (ladjust) {
+	padc = ' ';
+    }
+    if (negFlag && !ladjust && (padc == '0')) {
+	for (i = actualLength-1; i< length-1; i++) buf[i] = padc;
+	buf[length -1] = '-';
+    } else {
+	for (i = actualLength; i< length; i++) buf[i] = padc;
+    }
+	    
+
+    /* prepare to reverse the string */
+    {
+	int begin = 0;
+	int end;
+	if (ladjust) {
+	    end = actualLength - 1;
+	} else {
+	    end = length -1;
+	}
+
+	while (end > begin) {
+	    char tmp = buf[begin];
+	    buf[begin] = buf[end];
+	    buf[end] = tmp;
+	    begin ++;
+	    end --;
+	}
+    }
+
+    /* adjust the string pointer */
+    return length;
+}
diff --git a/target/linux/generic/image/lzma-loader/src/print.h b/target/linux/generic/image/lzma-loader/src/print.h
new file mode 100644
index 0000000..b051463
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/print.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef _print_h_
+#define _print_h_
+
+#include <stdarg.h>
+
+/* this is the maximum width for a variable */
+#define		LP_MAX_BUF	80
+
+/* -*-
+ * output function takes an void pointer which is passed in as the
+ * second argument in lp_Print().  This black-box argument gives output
+ * function a way to track state.
+ *
+ * The second argument in output function is a pointer to char buffer.
+ * The third argument specifies the number of chars to outputed.
+ *
+ * output function cannot assume the buffer is null-terminated after
+ * l number of chars.
+ */
+void lp_Print(void (*output)(void *, char *, int), 
+	      void * arg,
+	      char *fmt, 
+	      va_list ap);
+
+#endif
diff --git a/target/linux/generic/image/lzma-loader/src/printf.c b/target/linux/generic/image/lzma-loader/src/printf.c
new file mode 100644
index 0000000..49bd50d
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/printf.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include "printf.h"
+#include "print.h"
+#include "uart16550.h"
+
+static void myoutput(void *arg, char *s, int l)
+{
+    int i;
+
+    // special termination call
+    if ((l==1) && (s[0] == '\0')) return;
+    
+    for (i=0; i< l; i++) {
+	Uart16550Put(s[i]);
+	if (s[i] == '\n') Uart16550Put('\r');
+    }
+}
+
+void printf(char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    lp_Print(myoutput, 0, fmt, ap);
+    va_end(ap);
+}
diff --git a/target/linux/generic/image/lzma-loader/src/printf.h b/target/linux/generic/image/lzma-loader/src/printf.h
new file mode 100644
index 0000000..9b1c1df
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/printf.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef _printf_h_
+#define _printf_h_
+
+#include <stdarg.h>
+void printf(char *fmt, ...);
+
+#endif /* _printf_h_ */
diff --git a/target/linux/generic/image/lzma-loader/src/start.S b/target/linux/generic/image/lzma-loader/src/start.S
new file mode 100644
index 0000000..8642933
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/start.S
@@ -0,0 +1,160 @@
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#define KSEG0		0x80000000
+
+#define C0_CONFIG	$16
+#define C0_TAGLO	$28
+#define C0_TAGHI	$29
+
+#define	CONF1_DA_SHIFT	7			/* D$ associativity */
+#define CONF1_DA_MASK	0x00000380
+#define CONF1_DA_BASE	1
+#define CONF1_DL_SHIFT	10			/* D$ line size */
+#define CONF1_DL_MASK	0x00001c00
+#define CONF1_DL_BASE	2
+#define CONF1_DS_SHIFT	13			/* D$ sets/way */
+#define CONF1_DS_MASK	0x0000e000
+#define CONF1_DS_BASE	64
+#define CONF1_IA_SHIFT	16			/* I$ associativity */
+#define CONF1_IA_MASK	0x00070000
+#define CONF1_IA_BASE	1
+#define CONF1_IL_SHIFT	19			/* I$ line size */
+#define CONF1_IL_MASK	0x00380000
+#define CONF1_IL_BASE	2
+#define CONF1_IS_SHIFT	22			/* Instruction cache sets/way */
+#define CONF1_IS_MASK	0x01c00000
+#define CONF1_IS_BASE	64
+
+#define Index_Invalidate_I	0x00
+#define Index_Writeback_Inv_D   0x01
+
+LEAF(_start)
+	
+	.set	mips32
+	.set noreorder
+
+	/* save argument registers */
+	move t4, a0
+	move t5, a1
+	move t6, a2
+	move t7, a3
+	
+	/* set up stack */
+	li	sp, RAMSTART + RAMSIZE - 16
+
+#ifdef IMAGE_COPY
+	/* Copy decompressor code to the right place */
+	li  t2, LOADADDR
+	add a0, t2, 0
+	la  a1, code_start
+	la  a2, code_stop
+$L1:
+	lw  t0, 0(a1)
+	sw  t0, 0(a0)
+	add a1, 4
+	add a0, 4
+	blt a1, a2, $L1
+	nop
+#endif
+
+	/* At this point we need to invalidate dcache and */
+	/* icache before jumping to new code */
+
+1:	/* Get cache sizes */
+	mfc0	s0,C0_CONFIG,1
+
+	li	s1,CONF1_DL_MASK
+	and	s1,s0
+	beq	s1,zero,nodc
+	nop
+
+	srl	s1,CONF1_DL_SHIFT
+	li	t0,CONF1_DL_BASE
+	sll	s1,t0,s1		/* s1 has D$ cache line size */
+
+	li	s2,CONF1_DA_MASK
+	and	s2,s0
+	srl	s2,CONF1_DA_SHIFT
+	addiu	s2,CONF1_DA_BASE	/* s2 now has D$ associativity */
+
+	li	t0,CONF1_DS_MASK
+	and	t0,s0
+	srl	t0,CONF1_DS_SHIFT
+	li	s3,CONF1_DS_BASE
+	sll	s3,s3,t0		/* s3 has D$ sets per way */
+
+	multu	s2,s3			/* sets/way * associativity */
+	mflo	t0			/* total cache lines */
+
+	multu	s1,t0			/* D$ linesize * lines */
+	mflo	s2			/* s2 is now D$ size in bytes */
+
+	/* Initilize the D$: */
+	mtc0	zero,C0_TAGLO
+	mtc0	zero,C0_TAGHI
+
+	li	t0,KSEG0		/* Just an address for the first $ line */
+	addu	t1,t0,s2		/*  + size of cache == end */
+
+1:	cache	Index_Writeback_Inv_D,0(t0)
+	bne	t0,t1,1b
+	addu	t0,s1
+	
+nodc:
+	/* Now we get to do it all again for the I$ */
+	
+	move	s3,zero			/* just in case there is no icache */
+	move	s4,zero
+
+	li	t0,CONF1_IL_MASK
+	and	t0,s0
+	beq	t0,zero,noic
+	nop
+
+	srl	t0,CONF1_IL_SHIFT
+	li	s3,CONF1_IL_BASE
+	sll	s3,t0			/* s3 has I$ cache line size */
+
+	li	t0,CONF1_IA_MASK
+	and	t0,s0
+	srl	t0,CONF1_IA_SHIFT
+	addiu	s4,t0,CONF1_IA_BASE	/* s4 now has I$ associativity */
+
+	li	t0,CONF1_IS_MASK
+	and	t0,s0
+	srl	t0,CONF1_IS_SHIFT
+	li	s5,CONF1_IS_BASE
+	sll	s5,t0			/* s5 has I$ sets per way */
+
+	multu	s4,s5			/* sets/way * associativity */
+	mflo	t0			/* s4 is now total cache lines */
+
+	multu	s3,t0			/* I$ linesize * lines */
+	mflo	s4			/* s4 is cache size in bytes */
+
+	/* Initilize the I$: */
+	mtc0	zero,C0_TAGLO
+	mtc0	zero,C0_TAGHI
+
+	li	t0,KSEG0		/* Just an address for the first $ line */
+	addu	t1,t0,s4		/*  + size of cache == end */
+
+1:	cache	Index_Invalidate_I,0(t0)
+	bne	t0,t1,1b
+	addu	t0,s3
+noic:
+	/* jump to main */
+	move    a0,s3                   /* icache line size */
+	move    a1,s4                   /* icache size */
+	move    a2,s1                   /* dcache line size */
+#ifdef IMAGE_COPY
+	jal		t2
+#else
+	jal     entry
+#endif
+	move    a3,s2                   /* dcache size */
+
+	.set reorder
+END(_start)
+
diff --git a/target/linux/generic/image/lzma-loader/src/uart16550.c b/target/linux/generic/image/lzma-loader/src/uart16550.c
new file mode 100644
index 0000000..7df5727
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/uart16550.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+
+#include "uart16550.h"
+
+/* === CONFIG === */
+
+#define         BASE                    0xb8058000
+#define         MAX_BAUD                1152000
+#define         REG_OFFSET              4
+
+/* === END OF CONFIG === */
+
+/* register offset */
+#define         OFS_RCV_BUFFER          (0*REG_OFFSET)
+#define         OFS_TRANS_HOLD          (0*REG_OFFSET)
+#define         OFS_SEND_BUFFER         (0*REG_OFFSET)
+#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
+#define         OFS_INTR_ID             (2*REG_OFFSET)
+#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
+#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
+#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
+#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
+#define         OFS_LINE_STATUS         (5*REG_OFFSET)
+#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
+#define         OFS_RS232_INPUT         (6*REG_OFFSET)
+#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
+
+#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
+#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
+
+
+/* memory-mapped read/write of the port */
+#define         UART16550_READ(y)    (*((volatile uint32*)(BASE + y)))
+#define         UART16550_WRITE(y, z)  ((*((volatile uint32*)(BASE + y))) = z)
+
+#define DEBUG_LED (*(unsigned short*)0xb7ffffc0)
+#define OutputLED(x)  (DEBUG_LED = x)
+
+void Uart16550Init(uint32 baud, uint8 data, uint8 parity, uint8 stop)
+{
+    /* disable interrupts */
+    UART16550_WRITE(OFS_INTR_ENABLE, 0);
+
+    /* set up buad rate */
+    { 
+        uint32 divisor;
+       
+        /* set DIAB bit */
+        UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
+        
+        /* set divisor */
+        divisor = MAX_BAUD / baud;
+        UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
+        UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00)>>8);
+
+        /* clear DIAB bit */
+        UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
+    }
+
+    /* set data format */
+    UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
+}
+
+uint8 Uart16550GetPoll()
+{
+    while((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
+    return UART16550_READ(OFS_RCV_BUFFER);
+}
+
+
+void Uart16550Put(uint8 byte)
+{
+    while ((UART16550_READ(OFS_LINE_STATUS) &0x20) == 0);
+    UART16550_WRITE(OFS_SEND_BUFFER, byte);
+}
+
diff --git a/target/linux/generic/image/lzma-loader/src/uart16550.h b/target/linux/generic/image/lzma-loader/src/uart16550.h
new file mode 100644
index 0000000..b3fd6fd
--- /dev/null
+++ b/target/linux/generic/image/lzma-loader/src/uart16550.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.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 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef _uart16550_h_
+#define _uart16550_h_
+
+typedef         unsigned char uint8;
+typedef         unsigned int  uint32;
+
+#define         UART16550_BAUD_2400             2400
+#define         UART16550_BAUD_4800             4800
+#define         UART16550_BAUD_9600             9600
+#define         UART16550_BAUD_19200            19200
+#define         UART16550_BAUD_38400            38400
+#define         UART16550_BAUD_57600            57600
+#define         UART16550_BAUD_115200           115200
+
+#define         UART16550_PARITY_NONE           0
+#define         UART16550_PARITY_ODD            0x08
+#define         UART16550_PARITY_EVEN           0x18
+#define         UART16550_PARITY_MARK           0x28
+#define         UART16550_PARITY_SPACE          0x38
+
+#define         UART16550_DATA_5BIT             0x0
+#define         UART16550_DATA_6BIT             0x1
+#define         UART16550_DATA_7BIT             0x2
+#define         UART16550_DATA_8BIT             0x3
+
+#define         UART16550_STOP_1BIT             0x0
+#define         UART16550_STOP_2BIT             0x4
+
+void Uart16550Init(uint32 baud, uint8 data, uint8 parity, uint8 stop);
+
+/* blocking call */
+uint8 Uart16550GetPoll();
+
+void Uart16550Put(uint8 byte);
+
+#endif
-- 
cgit v1.2.3