[adm5120] lzma-loader improvements
authorGabor Juhos <juhosg@openwrt.org>
Sun, 15 Jul 2007 15:02:38 +0000 (15:02 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Sun, 15 Jul 2007 15:02:38 +0000 (15:02 +0000)
 * update LzmaDecode.[ch] to 4.16
 * speed up decompressing from flash
 * uses printf from lzma-loader of generic-2.6 target
 * initial support for flash bank switching

SVN-Revision: 7975

target/linux/adm5120-2.6/image/lzma-loader/src/LzmaDecode.c
target/linux/adm5120-2.6/image/lzma-loader/src/LzmaDecode.h
target/linux/adm5120-2.6/image/lzma-loader/src/Makefile
target/linux/adm5120-2.6/image/lzma-loader/src/board.c
target/linux/adm5120-2.6/image/lzma-loader/src/config.h
target/linux/adm5120-2.6/image/lzma-loader/src/decompress.c
target/linux/adm5120-2.6/image/lzma-loader/src/printf.c [new file with mode: 0644]
target/linux/adm5120-2.6/image/lzma-loader/src/printf.h [new file with mode: 0644]

index 951700b..75a358a 100644 (file)
@@ -1,8 +1,8 @@
 /*
   LzmaDecode.c
-  LZMA Decoder
+  LZMA Decoder (optimized for Speed version)
   
-  LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+  LZMA SDK 4.16 Copyright (c) 1999-2005 Igor Pavlov (2005-03-18)
   http://www.7-zip.org/
 
   LZMA SDK is licensed under two licenses:
@@ -12,9 +12,9 @@
   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 
+  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.
 */
 #define kBitModelTotal (1 << kNumBitModelTotalBits)
 #define kNumMoveBits 5
 
-typedef struct _CRangeDecoder
-{
-  Byte *Buffer;
-  Byte *BufferLim;
-  UInt32 Range;
-  UInt32 Code;
-  #ifdef _LZMA_IN_CB
-  ILzmaInCallback *InCallback;
-  int Result;
-  #endif
-  int ExtraBytes;
-} CRangeDecoder;
+#define RC_READ_BYTE (*Buffer++)
 
-Byte RangeDecoderReadByte(CRangeDecoder *rd)
-{
-  if (rd->Buffer == rd->BufferLim)
-  {
-    #ifdef _LZMA_IN_CB
-    UInt32 size;
-    rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
-    rd->BufferLim = rd->Buffer + size;
-    if (size == 0)
-    #endif
-    {
-      rd->ExtraBytes = 1;
-      return 0xFF;
-    }
-  }
-  return (*rd->Buffer++);
-}
+#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
+  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
 
-/* #define ReadByte (*rd->Buffer++) */
-#define ReadByte (RangeDecoderReadByte(rd))
+#ifdef _LZMA_IN_CB
 
-void RangeDecoderInit(CRangeDecoder *rd,
-  #ifdef _LZMA_IN_CB
-    ILzmaInCallback *inCallback
-  #else
-    Byte *stream, UInt32 bufferSize
-  #endif
-    )
-{
-  int i;
-  #ifdef _LZMA_IN_CB
-  rd->InCallback = inCallback;
-  rd->Buffer = rd->BufferLim = 0;
-  #else
-  rd->Buffer = stream;
-  rd->BufferLim = stream + bufferSize;
-  #endif
-  rd->ExtraBytes = 0;
-  rd->Code = 0;
-  rd->Range = (0xFFFFFFFF);
-  for(i = 0; i < 5; i++)
-    rd->Code = (rd->Code << 8) | ReadByte;
-}
+#define RC_TEST { if (Buffer == BufferLim) \
+  { UInt32 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_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;        
-#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
-#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
+#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
 
-UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
-{
-  RC_INIT_VAR
-  UInt32 result = 0;
-  int i;
-  for (i = numTotalBits; i > 0; i--)
-  {
-    /* UInt32 t; */
-    range >>= 1;
+#else
 
-    result <<= 1;
-    if (code >= range)
-    {
-      code -= range;
-      result |= 1;
-    }
-    /*
-    t = (code - range) >> 31;
-    t &= 1;
-    code -= range & (t - 1);
-    result = (result + result) | (1 - t);
-    */
-    RC_NORMALIZE
-  }
-  RC_FLUSH_VAR
-  return result;
-}
+#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
 
-int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
-{
-  UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
-  if (rd->Code < bound)
-  {
-    rd->Range = bound;
-    *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
-    if (rd->Range < kTopValue)
-    {
-      rd->Code = (rd->Code << 8) | ReadByte;
-      rd->Range <<= 8;
-    }
-    return 0;
-  }
-  else
-  {
-    rd->Range -= bound;
-    rd->Code -= bound;
-    *prob -= (*prob) >> kNumMoveBits;
-    if (rd->Range < kTopValue)
-    {
-      rd->Code = (rd->Code << 8) | ReadByte;
-      rd->Range <<= 8;
-    }
-    return 1;
-  }
-}
+#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
+#endif
 
-#define RC_GET_BIT2(prob, mi, A0, A1) \
-  UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
-  if (code < bound) \
-    { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
-  else \
-    { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
-  RC_NORMALIZE
+#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
 
-#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)               
+#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;
 
-int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
-{
-  int mi = 1;
-  int i;
-  #ifdef _LZMA_LOC_OPT
-  RC_INIT_VAR
-  #endif
-  for(i = numLevels; i > 0; i--)
-  {
-    #ifdef _LZMA_LOC_OPT
-    CProb *prob = probs + mi;
-    RC_GET_BIT(prob, mi)
-    #else
-    mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
-    #endif
-  }
-  #ifdef _LZMA_LOC_OPT
-  RC_FLUSH_VAR
-  #endif
-  return mi - (1 << numLevels);
-}
+#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, ; , ;)               
 
-int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
-{
-  int mi = 1;
-  int i;
-  int symbol = 0;
-  #ifdef _LZMA_LOC_OPT
-  RC_INIT_VAR
-  #endif
-  for(i = 0; i < numLevels; i++)
-  {
-    #ifdef _LZMA_LOC_OPT
-    CProb *prob = probs + mi;
-    RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
-    #else
-    int bit = RangeDecoderBitDecode(probs + mi, rd);
-    mi = mi + mi + bit;
-    symbol |= (bit << i);
-    #endif
-  }
-  #ifdef _LZMA_LOC_OPT
-  RC_FLUSH_VAR
-  #endif
-  return symbol;
-}
+#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); }
 
-Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
-{ 
-  int symbol = 1;
-  #ifdef _LZMA_LOC_OPT
-  RC_INIT_VAR
-  #endif
-  do
-  {
-    #ifdef _LZMA_LOC_OPT
-    CProb *prob = probs + symbol;
-    RC_GET_BIT(prob, symbol)
-    #else
-    symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
-    #endif
-  }
-  while (symbol < 0x100);
-  #ifdef _LZMA_LOC_OPT
-  RC_FLUSH_VAR
-  #endif
-  return symbol;
-}
-
-Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
-{ 
-  int symbol = 1;
-  #ifdef _LZMA_LOC_OPT
-  RC_INIT_VAR
-  #endif
-  do
-  {
-    int bit;
-    int matchBit = (matchByte >> 7) & 1;
-    matchByte <<= 1;
-    #ifdef _LZMA_LOC_OPT
-    {
-      CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
-      RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
-    }
-    #else
-    bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
-    symbol = (symbol << 1) | bit;
-    #endif
-    if (matchBit != bit)
-    {
-      while (symbol < 0x100)
-      {
-        #ifdef _LZMA_LOC_OPT
-        CProb *prob = probs + symbol;
-        RC_GET_BIT(prob, symbol)
-        #else
-        symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
-        #endif
-      }
-      break;
-    }
-  }
-  while (symbol < 0x100);
-  #ifdef _LZMA_LOC_OPT
-  RC_FLUSH_VAR
-  #endif
-  return symbol;
-}
 
 #define kNumPosBitsMax 4
 #define kNumPosStatesMax (1 << kNumPosBitsMax)
@@ -286,19 +88,9 @@ Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
 #define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
 
-int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
-{
-  if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
-    return RangeDecoderBitTreeDecode(p + LenLow +
-        (posState << kLenNumLowBits), kLenNumLowBits, rd);
-  if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
-    return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
-        (posState << kLenNumMidBits), kLenNumMidBits, rd);
-  return kLenNumLowSymbols + kLenNumMidSymbols + 
-      RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
-}
 
 #define kNumStates 12
+#define kNumLitStates 7
 
 #define kStartPosModelIndex 4
 #define kEndPosModelIndex 14
@@ -333,7 +125,13 @@ StopCompilingDueBUG
 
 typedef struct _LzmaVarState
 {
-  CRangeDecoder RangeDecoder;
+  Byte *Buffer;
+  Byte *BufferLim;
+  UInt32 Range;
+  UInt32 Code;
+  #ifdef _LZMA_IN_CB
+  ILzmaInCallback *InCallback;
+  #endif
   Byte *Dictionary;
   UInt32 DictionarySize;
   UInt32 DictionaryPos;
@@ -343,8 +141,8 @@ typedef struct _LzmaVarState
   int lp;
   int pb;
   int State;
-  int PreviousIsMatch;
   int RemainLen;
+  Byte TempDictionary[4];
 } LzmaVarState;
 
 int LzmaDecoderInit(
@@ -352,12 +150,16 @@ int LzmaDecoderInit(
     int lc, int lp, int pb,
     unsigned char *dictionary, UInt32 dictionarySize,
     #ifdef _LZMA_IN_CB
-    ILzmaInCallback *inCallback
+    ILzmaInCallback *InCallback
     #else
     unsigned char *inStream, UInt32 inSize
     #endif
     )
 {
+  Byte *Buffer;
+  Byte *BufferLim;
+  UInt32 Range;
+  UInt32 Code;
   LzmaVarState *vs = (LzmaVarState *)buffer;
   CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
   UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
@@ -373,18 +175,24 @@ int LzmaDecoderInit(
   vs->lp = lp;
   vs->pb = pb;
   vs->State = 0;
-  vs->PreviousIsMatch = 0;
   vs->RemainLen = 0;
   dictionary[dictionarySize - 1] = 0;
   for (i = 0; i < numProbs; i++)
     p[i] = kBitModelTotal >> 1; 
-  RangeDecoderInit(&vs->RangeDecoder, 
-      #ifdef _LZMA_IN_CB
-      inCallback
-      #else
-      inStream, inSize
-      #endif
-  );
+
+  #ifdef _LZMA_IN_CB
+  RC_INIT;
+  #else
+  RC_INIT(inStream, inSize);
+  #endif
+  vs->Buffer = Buffer;
+  vs->BufferLim = BufferLim;
+  vs->Range = Range;
+  vs->Code = Code;
+  #ifdef _LZMA_IN_CB
+  vs->InCallback = InCallback;
+  #endif
+
   return LZMA_RESULT_OK;
 }
 
@@ -393,10 +201,15 @@ int LzmaDecode(unsigned char *buffer,
     UInt32 *outSizeProcessed)
 {
   LzmaVarState *vs = (LzmaVarState *)buffer;
+  Byte *Buffer = vs->Buffer;
+  Byte *BufferLim = vs->BufferLim;
+  UInt32 Range = vs->Range;
+  UInt32 Code = vs->Code;
+  #ifdef _LZMA_IN_CB
+  ILzmaInCallback *InCallback = vs->InCallback;
+  #endif
   CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
-  CRangeDecoder rd = vs->RangeDecoder;
   int state = vs->State;
-  int previousIsMatch = vs->PreviousIsMatch;
   Byte previousByte;
   UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
   UInt32 nowPos = 0;
@@ -410,13 +223,21 @@ int LzmaDecode(unsigned char *buffer,
   UInt32 dictionarySize = vs->DictionarySize;
   UInt32 dictionaryPos = vs->DictionaryPos;
 
+  Byte tempDictionary[4];
+  if (dictionarySize == 0)
+  {
+    dictionary = tempDictionary;
+    dictionarySize = 1;
+    tempDictionary[0] = vs->TempDictionary[0];
+  }
+
   if (len == -1)
   {
     *outSizeProcessed = 0;
     return LZMA_RESULT_OK;
   }
 
-  while(len > 0 && nowPos < outSize)
+  while(len != 0 && nowPos < outSize)
   {
     UInt32 pos = dictionaryPos - rep0;
     if (pos >= dictionarySize)
@@ -436,7 +257,7 @@ int LzmaDecode(
     Byte *buffer, UInt32 bufferSize,
     int lc, int lp, int pb,
     #ifdef _LZMA_IN_CB
-    ILzmaInCallback *inCallback,
+    ILzmaInCallback *InCallback,
     #else
     unsigned char *inStream, UInt32 inSize,
     #endif
@@ -445,32 +266,39 @@ int LzmaDecode(
 {
   UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
   CProb *p = (CProb *)buffer;
-  CRangeDecoder rd;
+
   UInt32 i;
   int state = 0;
-  int previousIsMatch = 0;
   Byte previousByte = 0;
   UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
   UInt32 nowPos = 0;
   UInt32 posStateMask = (1 << pb) - 1;
   UInt32 literalPosMask = (1 << lp) - 1;
   int len = 0;
+  
+  Byte *Buffer;
+  Byte *BufferLim;
+  UInt32 Range;
+  UInt32 Code;
+  
   if (bufferSize < numProbs * sizeof(CProb))
     return LZMA_RESULT_NOT_ENOUGH_MEM;
   for (i = 0; i < numProbs; i++)
-    p[i] = kBitModelTotal >> 1; 
-  RangeDecoderInit(&rd, 
-      #ifdef _LZMA_IN_CB
-      inCallback
-      #else
-      inStream, inSize
-      #endif
-      );
+    p[i] = kBitModelTotal >> 1;
+  
+
+  #ifdef _LZMA_IN_CB
+  RC_INIT;
+  #else
+  RC_INIT(inStream, inSize);
+  #endif
 #endif
 
   *outSizeProcessed = 0;
   while(nowPos < outSize)
   {
+    CProb *prob;
+    UInt32 bound;
     int posState = (int)(
         (nowPos 
         #ifdef _LZMA_OUT_READ
@@ -478,15 +306,13 @@ int LzmaDecode(
         #endif
         )
         & posStateMask);
-    #ifdef _LZMA_IN_CB
-    if (rd.Result != LZMA_RESULT_OK)
-      return rd.Result;
-    #endif
-    if (rd.ExtraBytes != 0)
-      return LZMA_RESULT_DATA_ERROR;
-    if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
+
+    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
+    IfBit0(prob)
     {
-      CProb *probs = p + Literal + (LZMA_LIT_SIZE * 
+      int symbol = 1;
+      UpdateBit0(prob)
+      prob = p + Literal + (LZMA_LIT_SIZE * 
         (((
         (nowPos 
         #ifdef _LZMA_OUT_READ
@@ -495,12 +321,9 @@ int LzmaDecode(
         )
         & literalPosMask) << lc) + (previousByte >> (8 - lc))));
 
-      if (state < 4) state = 0;
-      else if (state < 10) state -= 3;
-      else state -= 6;
-      if (previousIsMatch)
+      if (state >= kNumLitStates)
       {
-        Byte matchByte;
+        int matchByte;
         #ifdef _LZMA_OUT_READ
         UInt32 pos = dictionaryPos - rep0;
         if (pos >= dictionarySize)
@@ -509,39 +332,71 @@ int LzmaDecode(
         #else
         matchByte = outStream[nowPos - rep0];
         #endif
-        previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
-        previousIsMatch = 0;
+        // prob += 0x100;
+        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);
+        // prob -= 0x100;
       }
-      else
-        previousByte = LzmaLiteralDecode(probs, &rd);
+      while (symbol < 0x100)
+      {
+        CProb *probLit = prob + symbol;
+        RC_GET_BIT(probLit, symbol)
+      }
+      previousByte = (Byte)symbol;
+
       outStream[nowPos++] = previousByte;
       #ifdef _LZMA_OUT_READ
       dictionary[dictionaryPos] = previousByte;
       if (++dictionaryPos == dictionarySize)
         dictionaryPos = 0;
       #endif
+      if (state < 4) state = 0;
+      else if (state < 10) state -= 3;
+      else state -= 6;
     }
     else             
     {
-      previousIsMatch = 1;
-      if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
+      // int isItRep;
+      UpdateBit1(prob);
+      prob = p + IsRep + state;
+      IfBit0(prob)
       {
-        if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
+        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)
         {
-          if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
+          UpdateBit0(prob);
+          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IfBit0(prob)
           {
             #ifdef _LZMA_OUT_READ
             UInt32 pos;
             #endif
-            if (
-               (nowPos 
+            UpdateBit0(prob);
+            if (nowPos 
                 #ifdef _LZMA_OUT_READ
                 + globalPos
                 #endif
-               )
-               == 0)
+                == 0)
               return LZMA_RESULT_DATA_ERROR;
-            state = state < 7 ? 9 : 11;
+            state = state < kNumLitStates ? 9 : 11;
             #ifdef _LZMA_OUT_READ
             pos = dictionaryPos - rep0;
             if (pos >= dictionarySize)
@@ -556,18 +411,33 @@ int LzmaDecode(
             outStream[nowPos++] = previousByte;
             continue;
           }
+          else
+          {
+            UpdateBit1(prob);
+          }
         }
         else
         {
           UInt32 distance;
-          if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
+          UpdateBit1(prob);
+          prob = p + IsRepG1 + state;
+          IfBit0(prob)
+          {
+            UpdateBit0(prob);
             distance = rep1;
+          }
           else 
           {
-            if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
+            UpdateBit1(prob);
+            prob = p + IsRepG2 + state;
+            IfBit0(prob)
+            {
+              UpdateBit0(prob);
               distance = rep2;
+            }
             else
             {
+              UpdateBit1(prob);
               distance = rep3;
               rep3 = rep2;
             }
@@ -576,55 +446,107 @@ int LzmaDecode(
           rep1 = rep0;
           rep0 = distance;
         }
-        len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
-        state = state < 7 ? 8 : 11;
+        state = state < kNumLitStates ? 8 : 11;
+        prob = p + RepLenCoder;
       }
-      else
+      {
+        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;
-        rep3 = rep2;
-        rep2 = rep1;
-        rep1 = rep0;
-        state = state < 7 ? 7 : 10;
-        len = LzmaLenDecode(p + LenCoder, &rd, posState);
-        posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
+        state += kNumLitStates;
+        prob = p + PosSlot +
             ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
-            kNumPosSlotBits), kNumPosSlotBits, &rd);
+            kNumPosSlotBits);
+        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
         if (posSlot >= kStartPosModelIndex)
         {
           int numDirectBits = ((posSlot >> 1) - 1);
-          rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
+          rep0 = (2 | ((UInt32)posSlot & 1));
           if (posSlot < kEndPosModelIndex)
           {
-            rep0 += RangeDecoderReverseBitTreeDecode(
-                p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
+            rep0 <<= numDirectBits;
+            prob = p + SpecPos + rep0 - posSlot - 1;
           }
           else
           {
-            rep0 += RangeDecoderDecodeDirectBits(&rd, 
-                numDirectBits - kNumAlignBits) << kNumAlignBits;
-            rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
+            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;
-        rep0++;
-      }
-      if (rep0 == (UInt32)(0))
-      {
-        /* it's for stream version */
-        len = -1;
-        break;
+        if (++rep0 == (UInt32)(0))
+        {
+          /* it's for stream version */
+          len = -1;
+          break;
+        }
       }
+
+      len += kMatchMinLen;
       if (rep0 > nowPos 
         #ifdef _LZMA_OUT_READ
-        + globalPos
+        + globalPos || rep0 > dictionarySize
         #endif
-        )
-      {
+        ) 
         return LZMA_RESULT_DATA_ERROR;
-      }
-      len += kMatchMinLen;
       do
       {
         #ifdef _LZMA_OUT_READ
@@ -638,15 +560,19 @@ int LzmaDecode(
         #else
         previousByte = outStream[nowPos - rep0];
         #endif
-        outStream[nowPos++] = previousByte;
         len--;
+        outStream[nowPos++] = previousByte;
       }
-      while(len > 0 && nowPos < outSize);
+      while(len != 0 && nowPos < outSize);
     }
   }
+  RC_NORMALIZE;
 
   #ifdef _LZMA_OUT_READ
-  vs->RangeDecoder = rd;
+  vs->Buffer = Buffer;
+  vs->BufferLim = BufferLim;
+  vs->Range = Range;
+  vs->Code = Code;
   vs->DictionaryPos = dictionaryPos;
   vs->GlobalPos = globalPos + nowPos;
   vs->Reps[0] = rep0;
@@ -654,8 +580,8 @@ int LzmaDecode(
   vs->Reps[2] = rep2;
   vs->Reps[3] = rep3;
   vs->State = state;
-  vs->PreviousIsMatch = previousIsMatch;
   vs->RemainLen = len;
+  vs->TempDictionary[0] = tempDictionary[0];
   #endif
 
   *outSizeProcessed = nowPos;
index f58944e..5367735 100644 (file)
@@ -2,7 +2,7 @@
   LzmaDecode.h
   LZMA Decoder interface
 
-  LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
+  LZMA SDK 4.16 Copyright (c) 1999-2005 Igor Pavlov (2005-03-18)
   http://www.7-zip.org/
 
   LZMA SDK is licensed under two licenses:
index a3749f2..7e9d8d0 100644 (file)
@@ -38,6 +38,7 @@ BIN_FLAGS     := -O binary -R .reginfo -R .note -R .comment -R .mdebug -S
 CFLAGS         = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
                  -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic \
                  -ffunction-sections -pipe -mlong-calls -fno-common \
+                 -ffreestanding \
                  -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
 CFLAGS         += -DLOADADDR=$(LOADADDR)
 
@@ -48,7 +49,7 @@ LDFLAGS               += -e startup -T loader.lds -Ttext $(LZMA_TEXT_START)
 
 O_FORMAT       = $(shell $(OBJDUMP) -i | head -2 | grep elf32)
 
-OBJECTS                := head.o decompress.o board.o LzmaDecode.o
+OBJECTS                := head.o decompress.o board.o printf.o LzmaDecode.o
 
 ifneq ($(strip $(LOADER_DATA)),)
 OBJECTS                += data.o
index baffe04..2425b7d 100644 (file)
@@ -121,15 +121,6 @@ static void uart_init(void)
 #endif
 }
 
-static void uart_putc(int ch)
-{
-       while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0);
-
-       UART_WRITE(UART_REG_DATA, ch);
-
-       while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0);
-}
-
 /*
  * INTC routines
  */
@@ -170,12 +161,13 @@ static void switch_init(void)
        SWITCH_WRITE(SWITCH_REG_PORT4_LED, 0);
 }
 
-/*
- *  routines needed by decompress.c
- */
 void board_putc(int ch)
 {
-       uart_putc(ch);
+       while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0);
+
+       UART_WRITE(UART_REG_DATA, ch);
+
+       while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0);
 }
 
 void board_init(void)
index 5002b18..b90fcfb 100644 (file)
@@ -1,37 +1,51 @@
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+#define FLASH_2M       (2<<20)
+#define FLASH_4M       (4<<20)
+
 /*
  * Cellvision/SparkLAN boards
  */
 
 #if defined(CONFIG_BOARD_CAS630)
 #  define CONFIG_BOARD_NAME    "CAS-630"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_CAS670)
 #  define CONFIG_BOARD_NAME    "CAS-670"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_CAS700)
 #  define CONFIG_BOARD_NAME    "CAS-700"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_CAS790)
 #  define CONFIG_BOARD_NAME    "CAS-790"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_CAS771)
 #  define CONFIG_BOARD_NAME    "CAS-771"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_CAS861)
 #  define CONFIG_BOARD_NAME    "CAS-861"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_NFS101U)
 #  define CONFIG_BOARD_NAME    "NFS-101U"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_NFS202U)
 #  define CONFIG_BOARD_NAME    "NFS-202U"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 /*
  */
 #if defined(CONFIG_BOARD_BR6104K)
 #  define CONFIG_BOARD_NAME    "BR-6104K"
+#  define CONFIG_FLASH_SIZE    FLASH_2M
 #endif
 
 #if defined(CONFIG_BOARD_BR6104KP)
 #  define CONFIG_BOARD_NAME    "BR-6104KP"
+#  define CONFIG_FLASH_SIZE    FLASH_2M
 #endif
 
 /*
@@ -62,6 +78,7 @@
 
 #if defined(CONFIG_BOARD_EASY83000)
 #  define CONFIG_BOARD_NAME    "EASY 83000"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 /*
  */
 #if defined(CONFIG_BOARD_P334WT)
 #  define CONFIG_BOARD_NAME    "P-334WT"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 #if defined(CONFIG_BOARD_P335)
 #  define CONFIG_BOARD_NAME    "P-335"
+#  define CONFIG_FLASH_SIZE    FLASH_4M
 #endif
 
 /*
 #ifndef CONFIG_BOARD_NAME
 #  define CONFIG_BOARD_NAME    "ADM5120"
 #endif
+
+#ifndef CONFIG_FLASH_SIZE
+#  define CONFIG_FLASH_SIZE    FLASH_2M
+#endif
+
+#endif /* _CONFIG_H_ */
\ No newline at end of file
index e2f9bee..9e2a04c 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * $Id$
+ *
  * LZMA compressed kernel decompressor for ADM5120 boards
  *
  * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
@@ -43,6 +45,7 @@
 #include <stddef.h>
 
 #include "config.h"
+#include "printf.h"
 #include "LzmaDecode.h"
 
 #define ADM5120_FLASH_START    0x1fc00000      /* Flash start */
                : "r" (base),                   \
                  "i" (op));
 
+#ifdef LZMA_DEBUG
+#  define DBG(f, a...) printf(f, ## a)
+#else
+#  define DBG(f, a...) do {} while (0)
+#endif
+
 static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
 {
        unsigned long start = KSEG0;
@@ -100,21 +109,22 @@ struct trx_header {
        unsigned int offsets[3];        /* Offsets of partitions from start of header */
 };
 
-/* beyound the image end, size not known in advance */
-extern unsigned char workspace[];
-#if LZMA_WRAPPER
-extern unsigned char _lzma_data_start[];
-extern unsigned char _lzma_data_end[];
-#endif
-
-extern void board_init(void);
-extern void board_putc(int ch);
-
 struct env_var {
        char    *name;
        char    *value;
 };
 
+/* beyound the image end, size not known in advance */
+extern unsigned char workspace[];
+extern void board_init(void);
+
+typedef void (*kernel_entry)(unsigned long reg_a0, unsigned long reg_a1,
+       unsigned long reg_a2, unsigned long reg_a3);
+
+static int decompress_data(unsigned char *buffer, UInt32 bufferSize,
+       int lc, int lp, int pb, unsigned char *outStream, UInt32 outSize,
+       UInt32 *outSizeProcessed);
+
 #ifdef CONFIG_PASS_KARGS
 #define ENVV(n,v)      {.name = (n), .value = (v)}
 struct env_var env_vars[] = {
@@ -123,111 +133,144 @@ struct env_var env_vars[] = {
 };
 #endif
 
+static void halt(void)
+{
+       printf("\nSystem halted!\n");
+       for(;;);
+}
+
+#if LZMA_WRAPPER
+extern unsigned char _lzma_data_start[];
+extern unsigned char _lzma_data_end[];
+
 unsigned char *data;
 unsigned long datalen;
 
-typedef void (*kernel_entry)(unsigned long reg_a0, unsigned long reg_a1,
-       unsigned long reg_a2, unsigned long reg_a3);
-
-static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
+static __inline__ unsigned char get_byte(void)
 {
-       *bufferSize = 1;
-       *buffer = data++;
-
-       return LZMA_RESULT_OK;
+       datalen--;
+       return *data++;
 }
 
-static __inline__ unsigned char get_byte(void)
+static void decompress_init(void)
 {
-       unsigned char *buffer;
-       UInt32 fake;
-
-       read_byte(0, &buffer, &fake);
-       return *buffer;
+       data = _lzma_data_start;
+       datalen = _lzma_data_end - _lzma_data_start;
 }
 
-static __inline__ unsigned int read_le32(void *buf)
+static int decompress_data(unsigned char *buffer, UInt32 bufferSize,
+       int lc, int lp, int pb, unsigned char *outStream, UInt32 outSize,
+       UInt32 *outSizeProcessed)
 {
-       unsigned char *p;
-
-       p = buf;
-       return ((unsigned int)p[0] + ((unsigned int)p[1] << 8) +
-               ((unsigned int)p[2] << 16) +((unsigned int)p[3] << 24));
+       return LzmaDecode(buffer, bufferSize, lc, lp, pb, data, datalen,
+               outStream, outSize, outSizeProcessed);
 }
+#endif /* LZMA_WRAPPER */
+
+#if !(LZMA_WRAPPER)
+
+#define FLASH_BANK_SIZE        (2<<20)
 
-static void print_char(char ch)
+static unsigned char *flash_base = (unsigned char *) KSEG1ADDR(ADM5120_FLASH_START);
+static unsigned long flash_ofs = 0;
+static unsigned long flash_max = 0;
+static unsigned long flash_ofs_mask = (FLASH_BANK_SIZE-1);
+
+static __inline__ unsigned char get_byte(void)
 {
-       if (ch == '\n')
-               board_putc('\r');
-       board_putc(ch);
+       return *(flash_base+flash_ofs++);
 }
 
-static void print_str(char * str)
+static int lzma_read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
 {
-       while ( *str != 0 )
-               print_char(*str++);
+       unsigned long len;
+
+       if (flash_ofs >= flash_max)
+               return LZMA_RESULT_DATA_ERROR;
+
+       len = flash_max-flash_ofs;
+
+#if (CONFIG_FLASH_SIZE > FLASH_BANK_SIZE)
+       if (flash_ofs < FLASH_BANK_SIZE) {
+               /* switch to bank 0 */
+               DBG("lzma_read_byte: switch to bank 0\n");
+
+               if (len > FLASH_BANK_SIZE-flash_ofs)
+                       len = FLASH_BANK_SIZE-flash_ofs;
+       } else {
+               /* switch to bank 1 */
+               DBG("lzma_read_byte: switch to bank 1\n");
+       }
+#endif
+       DBG("lzma_read_byte: ofs=%08X, len=%08X\n", flash_ofs, len);
+
+       *buffer = flash_base+(flash_ofs & flash_ofs_mask);
+       *bufferSize = len;
+       flash_ofs += len;
+
+       return LZMA_RESULT_OK;
 }
 
-static void print_hex(int val)
+static ILzmaInCallback lzma_callback = {
+       .Read   = lzma_read_byte,
+};
+
+static __inline__ unsigned int read_le32(void *buf)
 {
-       int i;
-       int tmp;
-
-       print_str("0x");
-       for ( i=0 ; i<8 ; i++ ) {
-               tmp = (val >> ((7-i) * 4 )) & 0xf;
-               tmp = tmp < 10 ? (tmp + '0') : (tmp + 'A' - 10);
-               board_putc(tmp);
-       }
+       unsigned char *p = buf;
+
+       return ((unsigned int)p[0] + ((unsigned int)p[1] << 8) +
+               ((unsigned int)p[2] << 16) +((unsigned int)p[3] << 24));
 }
 
-#if !(LZMA_WRAPPER)
-static unsigned char *find_kernel(void)
+static void decompress_init(void)
 {
-       struct trx_header *hdr;
-       unsigned char *ret;
+       struct trx_header *hdr = NULL;
+       unsigned long kofs,klen;
 
-       print_str("Looking for TRX header... ");
+       printf("Looking for TRX header... ");
        /* look for trx header, 32-bit data access */
-       hdr = NULL;
-       for (ret = ((unsigned char *) KSEG1ADDR(ADM5120_FLASH_START));
-               ret < ((unsigned char *)KSEG1ADDR(ADM5120_FLASH_END));
-               ret += TRX_ALIGN) {
-
-               if (read_le32(ret) == TRX_MAGIC) {
-                       hdr = (struct trx_header *)ret;
+       for (flash_ofs = 0; flash_ofs < FLASH_BANK_SIZE; flash_ofs += TRX_ALIGN) {
+               if (read_le32(&flash_base[flash_ofs]) == TRX_MAGIC) {
+                       hdr = (struct trx_header *)&flash_base[flash_ofs];
                        break;
                }
        }
 
        if (hdr == NULL) {
-               print_str("not found!\n");
-               return NULL;
+               printf("not found!\n");
+               /* no compressed kernel found, halting */
+               halt();
        }
 
-       print_str("found at ");
-       print_hex((unsigned int)ret);
-       print_str(", kernel in partition ");
-
        /* compressed kernel is in the partition 0 or 1 */
-       if ((read_le32(&hdr->offsets[1]) == 0) ||
-               (read_le32(&hdr->offsets[1]) > 65536)) {
-               ret += read_le32(&hdr->offsets[0]);
-               print_str("0\n");
+       kofs = read_le32(&hdr->offsets[1]);
+       if (kofs == 0 || kofs > 65536) {
+               klen = kofs-read_le32(&hdr->offsets[0]);
+               kofs = read_le32(&hdr->offsets[0]);
        } else {
-               ret += read_le32(&hdr->offsets[1]);
-               print_str("1\n");
+               klen = read_le32(&hdr->offsets[2]);
+               if (klen > kofs)
+                       klen -= kofs;
+               else
+                       klen = read_le32(&hdr->len)-kofs;
        }
 
-       return ret;
+       printf("found at %08X, kernel:%08X len:%08X\n", flash_ofs,
+               kofs, klen);
+
+       flash_ofs += kofs;
+       flash_max = flash_ofs+klen;
 }
-#endif /* !(LZMA_WRAPPER) */
 
-static void halt(void)
+static int decompress_data(unsigned char *buffer, UInt32 bufferSize,
+       int lc, int lp, int pb, unsigned char *outStream, UInt32 outSize,
+       UInt32 *outSizeProcessed)
 {
-       print_str("\nSystem halted!\n");
-       for(;;);
+       return LzmaDecode(buffer, bufferSize, lc, lp, pb, &lzma_callback,
+               outStream, outSize, outSizeProcessed);
 }
+#endif /* !(LZMA_WRAPPER) */
 
 /* should be the first function */
 void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
@@ -241,27 +284,13 @@ void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
        unsigned int pb; /* pos state bits */
        unsigned int osize; /* uncompressed size */
        int res;
-#if !(LZMA_WRAPPER)
-       ILzmaInCallback callback;
-#endif
 
        board_init();
 
-       print_str("\n\nLZMA loader for " CONFIG_BOARD_NAME
+       printf("\n\nLZMA loader for " CONFIG_BOARD_NAME
                        ", Copyright (C) 2007 OpenWrt.org\n\n");
 
-#if LZMA_WRAPPER
-       data = _lzma_data_start;
-       datalen = _lzma_data_end - _lzma_data_start;
-#else
-       data = find_kernel();
-       if (data == NULL) {
-               /* no compressed kernel found, halting */
-               halt();
-       }
-
-       datalen = ((unsigned char *) KSEG1ADDR(ADM5120_FLASH_END))-data;
-#endif
+       decompress_init();
 
        /* lzma args */
        i = get_byte();
@@ -282,41 +311,32 @@ void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
        for (i = 0; i < 4; i++)
                get_byte();
 
-       print_str("decompressing kernel... ");
+       printf("decompressing kernel... ");
 
        /* decompress kernel */
-#if LZMA_WRAPPER
-       res = LzmaDecode(workspace, ~0, lc, lp, pb, data, datalen,
-               (unsigned char*)LOADADDR, osize, &i);
-#else
-       callback.Read = read_byte;
-       res = LzmaDecode(workspace, ~0, lc, lp, pb, &callback,
-               (unsigned char*)LOADADDR, osize, &i);
-#endif
+       res = decompress_data(workspace, ~0, lc, lp, pb,
+               (unsigned char *)LOADADDR, osize, &i);
+
        if (res != LZMA_RESULT_OK) {
-               print_str("failed!\n");
-               print_str("LzmaDecode: ");
+               printf("failed, ");
                switch (res) {
                case LZMA_RESULT_DATA_ERROR:
-                       print_str("data error\n");
+                       printf("data error!\n");
                        break;
                case LZMA_RESULT_NOT_ENOUGH_MEM:
-                       print_str("not enough memory\n");
+                       printf("not enough memory!\n");
                        break;
                default:
-                       print_str("unknown error, err=0x");
-                       print_hex(res);
-                       print_str("\n");
+                       printf("unknown error %d!\n", res);
                }
                halt();
-       }
-
-        print_str("done!\n");
+       } else
+               printf("done!\n");
 
        blast_dcache(dcache_size, dcache_lsize);
        blast_icache(icache_size, icache_lsize);
 
-       print_str("launching kernel...\n\n");
+       printf("launching kernel...\n\n");
 
 #ifdef CONFIG_PASS_KARGS
        reg_a0 = 0;
diff --git a/target/linux/adm5120-2.6/image/lzma-loader/src/printf.c b/target/linux/adm5120-2.6/image/lzma-loader/src/printf.c
new file mode 100644 (file)
index 0000000..7bb5a86
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * 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"
+
+extern void board_putc(int ch);
+
+/* this is the maximum width for a variable */
+#define                LP_MAX_BUF      256
+
+/* macros */
+#define                IsDigit(x)      ( ((x) >= '0') && ((x) <= '9') )
+#define                Ctod(x)         ( (x) - '0')
+
+/* forward declaration */
+static int PrintChar(char *, char, int, int);
+static int PrintString(char *, char *, int, int);
+static 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.
+ */
+static 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 --------------------- */
+static 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;
+}
+
+static 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;
+}
+
+static 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;
+}
+
+static void printf_output(void *arg, char *s, int l)
+{
+    int i;
+
+    // special termination call
+    if ((l==1) && (s[0] == '\0')) return;
+
+    for (i=0; i< l; i++) {
+       board_putc(s[i]);
+       if (s[i] == '\n') board_putc('\r');
+    }
+}
+
+void printf(char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    lp_Print(printf_output, 0, fmt, ap);
+    va_end(ap);
+}
diff --git a/target/linux/adm5120-2.6/image/lzma-loader/src/printf.h b/target/linux/adm5120-2.6/image/lzma-loader/src/printf.h
new file mode 100644 (file)
index 0000000..9b1c1df
--- /dev/null
@@ -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_ */