lzma-loader improvements * 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
This commit is contained in:
Gabor Juhos 2007-07-15 15:02:38 +00:00
parent 57f4fc91ed
commit 93a7dd0956
8 changed files with 796 additions and 464 deletions

View file

@ -1,8 +1,8 @@
/* /*
LzmaDecode.c 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/ http://www.7-zip.org/
LZMA SDK is licensed under two licenses: LZMA SDK is licensed under two licenses:
@ -12,9 +12,9 @@
follow rules of that license. follow rules of that license.
SPECIAL EXCEPTION: SPECIAL EXCEPTION:
Igor Pavlov, as the author of this code, expressly permits you to Igor Pavlov, as the author of this Code, expressly permits you to
statically or dynamically link your code (or bind by name) to the statically or dynamically link your Code (or bind by name) to the
interfaces of this file without subjecting your linked code to the interfaces of this file without subjecting your linked Code to the
terms of the CPL or GNU LGPL. Any modifications or additions terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms. to this file, however, are subject to the LGPL or CPL terms.
*/ */
@ -32,242 +32,44 @@
#define kBitModelTotal (1 << kNumBitModelTotalBits) #define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5 #define kNumMoveBits 5
typedef struct _CRangeDecoder #define RC_READ_BYTE (*Buffer++)
{
Byte *Buffer;
Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#ifdef _LZMA_IN_CB
ILzmaInCallback *InCallback;
int Result;
#endif
int ExtraBytes;
} CRangeDecoder;
Byte RangeDecoderReadByte(CRangeDecoder *rd) #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
{ { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
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 ReadByte (*rd->Buffer++) */ #ifdef _LZMA_IN_CB
#define ReadByte (RangeDecoderReadByte(rd))
void RangeDecoderInit(CRangeDecoder *rd, #define RC_TEST { if (Buffer == BufferLim) \
#ifdef _LZMA_IN_CB { UInt32 size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
ILzmaInCallback *inCallback BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
#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_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code; #define RC_INIT Buffer = BufferLim = 0; RC_INIT2
#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits) #else
{
RC_INIT_VAR
UInt32 result = 0;
int i;
for (i = numTotalBits; i > 0; i--)
{
/* UInt32 t; */
range >>= 1;
result <<= 1; #define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
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;
}
int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd) #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
{
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_GET_BIT2(prob, mi, A0, A1) \ #endif
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_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;) #define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
{ #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
int mi = 1; #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
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);
}
int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd) #define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
{ { UpdateBit0(p); mi <<= 1; A0; } else \
int mi = 1; { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
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;
}
Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd) #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
{
int symbol = 1; #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
#ifdef _LZMA_LOC_OPT { int i = numLevels; res = 1; \
RC_INIT_VAR do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
#endif res -= (1 << numLevels); }
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 kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax) #define kNumPosStatesMax (1 << kNumPosBitsMax)
@ -286,19 +88,9 @@ Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols) #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 kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4 #define kStartPosModelIndex 4
#define kEndPosModelIndex 14 #define kEndPosModelIndex 14
@ -333,7 +125,13 @@ StopCompilingDueBUG
typedef struct _LzmaVarState typedef struct _LzmaVarState
{ {
CRangeDecoder RangeDecoder; Byte *Buffer;
Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#ifdef _LZMA_IN_CB
ILzmaInCallback *InCallback;
#endif
Byte *Dictionary; Byte *Dictionary;
UInt32 DictionarySize; UInt32 DictionarySize;
UInt32 DictionaryPos; UInt32 DictionaryPos;
@ -343,8 +141,8 @@ typedef struct _LzmaVarState
int lp; int lp;
int pb; int pb;
int State; int State;
int PreviousIsMatch;
int RemainLen; int RemainLen;
Byte TempDictionary[4];
} LzmaVarState; } LzmaVarState;
int LzmaDecoderInit( int LzmaDecoderInit(
@ -352,12 +150,16 @@ int LzmaDecoderInit(
int lc, int lp, int pb, int lc, int lp, int pb,
unsigned char *dictionary, UInt32 dictionarySize, unsigned char *dictionary, UInt32 dictionarySize,
#ifdef _LZMA_IN_CB #ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback ILzmaInCallback *InCallback
#else #else
unsigned char *inStream, UInt32 inSize unsigned char *inStream, UInt32 inSize
#endif #endif
) )
{ {
Byte *Buffer;
Byte *BufferLim;
UInt32 Range;
UInt32 Code;
LzmaVarState *vs = (LzmaVarState *)buffer; LzmaVarState *vs = (LzmaVarState *)buffer;
CProb *p = (CProb *)(buffer + sizeof(LzmaVarState)); CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
@ -373,18 +175,24 @@ int LzmaDecoderInit(
vs->lp = lp; vs->lp = lp;
vs->pb = pb; vs->pb = pb;
vs->State = 0; vs->State = 0;
vs->PreviousIsMatch = 0;
vs->RemainLen = 0; vs->RemainLen = 0;
dictionary[dictionarySize - 1] = 0; dictionary[dictionarySize - 1] = 0;
for (i = 0; i < numProbs; i++) for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1; p[i] = kBitModelTotal >> 1;
RangeDecoderInit(&vs->RangeDecoder,
#ifdef _LZMA_IN_CB #ifdef _LZMA_IN_CB
inCallback RC_INIT;
#else #else
inStream, inSize RC_INIT(inStream, inSize);
#endif #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; return LZMA_RESULT_OK;
} }
@ -393,10 +201,15 @@ int LzmaDecode(unsigned char *buffer,
UInt32 *outSizeProcessed) UInt32 *outSizeProcessed)
{ {
LzmaVarState *vs = (LzmaVarState *)buffer; 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)); CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
CRangeDecoder rd = vs->RangeDecoder;
int state = vs->State; int state = vs->State;
int previousIsMatch = vs->PreviousIsMatch;
Byte previousByte; Byte previousByte;
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
UInt32 nowPos = 0; UInt32 nowPos = 0;
@ -410,13 +223,21 @@ int LzmaDecode(unsigned char *buffer,
UInt32 dictionarySize = vs->DictionarySize; UInt32 dictionarySize = vs->DictionarySize;
UInt32 dictionaryPos = vs->DictionaryPos; UInt32 dictionaryPos = vs->DictionaryPos;
Byte tempDictionary[4];
if (dictionarySize == 0)
{
dictionary = tempDictionary;
dictionarySize = 1;
tempDictionary[0] = vs->TempDictionary[0];
}
if (len == -1) if (len == -1)
{ {
*outSizeProcessed = 0; *outSizeProcessed = 0;
return LZMA_RESULT_OK; return LZMA_RESULT_OK;
} }
while(len > 0 && nowPos < outSize) while(len != 0 && nowPos < outSize)
{ {
UInt32 pos = dictionaryPos - rep0; UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize) if (pos >= dictionarySize)
@ -436,7 +257,7 @@ int LzmaDecode(
Byte *buffer, UInt32 bufferSize, Byte *buffer, UInt32 bufferSize,
int lc, int lp, int pb, int lc, int lp, int pb,
#ifdef _LZMA_IN_CB #ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback, ILzmaInCallback *InCallback,
#else #else
unsigned char *inStream, UInt32 inSize, unsigned char *inStream, UInt32 inSize,
#endif #endif
@ -445,32 +266,39 @@ int LzmaDecode(
{ {
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp)); UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
CProb *p = (CProb *)buffer; CProb *p = (CProb *)buffer;
CRangeDecoder rd;
UInt32 i; UInt32 i;
int state = 0; int state = 0;
int previousIsMatch = 0;
Byte previousByte = 0; Byte previousByte = 0;
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
UInt32 nowPos = 0; UInt32 nowPos = 0;
UInt32 posStateMask = (1 << pb) - 1; UInt32 posStateMask = (1 << pb) - 1;
UInt32 literalPosMask = (1 << lp) - 1; UInt32 literalPosMask = (1 << lp) - 1;
int len = 0; int len = 0;
Byte *Buffer;
Byte *BufferLim;
UInt32 Range;
UInt32 Code;
if (bufferSize < numProbs * sizeof(CProb)) if (bufferSize < numProbs * sizeof(CProb))
return LZMA_RESULT_NOT_ENOUGH_MEM; return LZMA_RESULT_NOT_ENOUGH_MEM;
for (i = 0; i < numProbs; i++) for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1; p[i] = kBitModelTotal >> 1;
RangeDecoderInit(&rd,
#ifdef _LZMA_IN_CB
inCallback #ifdef _LZMA_IN_CB
#else RC_INIT;
inStream, inSize #else
#endif RC_INIT(inStream, inSize);
); #endif
#endif #endif
*outSizeProcessed = 0; *outSizeProcessed = 0;
while(nowPos < outSize) while(nowPos < outSize)
{ {
CProb *prob;
UInt32 bound;
int posState = (int)( int posState = (int)(
(nowPos (nowPos
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
@ -478,15 +306,13 @@ int LzmaDecode(
#endif #endif
) )
& posStateMask); & posStateMask);
#ifdef _LZMA_IN_CB
if (rd.Result != LZMA_RESULT_OK) prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
return rd.Result; IfBit0(prob)
#endif
if (rd.ExtraBytes != 0)
return LZMA_RESULT_DATA_ERROR;
if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
{ {
CProb *probs = p + Literal + (LZMA_LIT_SIZE * int symbol = 1;
UpdateBit0(prob)
prob = p + Literal + (LZMA_LIT_SIZE *
((( (((
(nowPos (nowPos
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
@ -495,12 +321,9 @@ int LzmaDecode(
) )
& literalPosMask) << lc) + (previousByte >> (8 - lc)))); & literalPosMask) << lc) + (previousByte >> (8 - lc))));
if (state < 4) state = 0; if (state >= kNumLitStates)
else if (state < 10) state -= 3;
else state -= 6;
if (previousIsMatch)
{ {
Byte matchByte; int matchByte;
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0; UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize) if (pos >= dictionarySize)
@ -509,39 +332,71 @@ int LzmaDecode(
#else #else
matchByte = outStream[nowPos - rep0]; matchByte = outStream[nowPos - rep0];
#endif #endif
previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte); // prob += 0x100;
previousIsMatch = 0; 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 while (symbol < 0x100)
previousByte = LzmaLiteralDecode(probs, &rd); {
CProb *probLit = prob + symbol;
RC_GET_BIT(probLit, symbol)
}
previousByte = (Byte)symbol;
outStream[nowPos++] = previousByte; outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
dictionary[dictionaryPos] = previousByte; dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize) if (++dictionaryPos == dictionarySize)
dictionaryPos = 0; dictionaryPos = 0;
#endif #endif
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
} }
else else
{ {
previousIsMatch = 1; // int isItRep;
if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1) 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 #ifdef _LZMA_OUT_READ
UInt32 pos; UInt32 pos;
#endif #endif
if ( UpdateBit0(prob);
(nowPos if (nowPos
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
+ globalPos + globalPos
#endif #endif
) == 0)
== 0)
return LZMA_RESULT_DATA_ERROR; return LZMA_RESULT_DATA_ERROR;
state = state < 7 ? 9 : 11; state = state < kNumLitStates ? 9 : 11;
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
pos = dictionaryPos - rep0; pos = dictionaryPos - rep0;
if (pos >= dictionarySize) if (pos >= dictionarySize)
@ -556,18 +411,33 @@ int LzmaDecode(
outStream[nowPos++] = previousByte; outStream[nowPos++] = previousByte;
continue; continue;
} }
else
{
UpdateBit1(prob);
}
} }
else else
{ {
UInt32 distance; UInt32 distance;
if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0) UpdateBit1(prob);
prob = p + IsRepG1 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep1; distance = rep1;
}
else else
{ {
if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0) UpdateBit1(prob);
prob = p + IsRepG2 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep2; distance = rep2;
}
else else
{ {
UpdateBit1(prob);
distance = rep3; distance = rep3;
rep3 = rep2; rep3 = rep2;
} }
@ -576,55 +446,107 @@ int LzmaDecode(
rep1 = rep0; rep1 = rep0;
rep0 = distance; rep0 = distance;
} }
len = LzmaLenDecode(p + RepLenCoder, &rd, posState); state = state < kNumLitStates ? 8 : 11;
state = state < 7 ? 8 : 11; prob = p + RepLenCoder;
} }
else
{ {
int posSlot; int numBits, offset;
rep3 = rep2; CProb *probLen = prob + LenChoice;
rep2 = rep1; IfBit0(probLen)
rep1 = rep0;
state = state < 7 ? 7 : 10;
len = LzmaLenDecode(p + LenCoder, &rd, posState);
posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits), kNumPosSlotBits, &rd);
if (posSlot >= kStartPosModelIndex)
{ {
int numDirectBits = ((posSlot >> 1) - 1); UpdateBit0(probLen);
rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits); probLen = prob + LenLow + (posState << kLenNumLowBits);
if (posSlot < kEndPosModelIndex) offset = 0;
numBits = kLenNumLowBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenChoice2;
IfBit0(probLen)
{ {
rep0 += RangeDecoderReverseBitTreeDecode( UpdateBit0(probLen);
p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd); probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
numBits = kLenNumMidBits;
} }
else else
{ {
rep0 += RangeDecoderDecodeDirectBits(&rd, UpdateBit1(probLen);
numDirectBits - kNumAlignBits) << kNumAlignBits; probLen = prob + LenHigh;
rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd); 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 else
rep0 = posSlot; rep0 = posSlot;
rep0++; if (++rep0 == (UInt32)(0))
} {
if (rep0 == (UInt32)(0)) /* it's for stream version */
{ len = -1;
/* it's for stream version */ break;
len = -1; }
break;
} }
len += kMatchMinLen;
if (rep0 > nowPos if (rep0 > nowPos
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
+ globalPos + globalPos || rep0 > dictionarySize
#endif #endif
) )
{
return LZMA_RESULT_DATA_ERROR; return LZMA_RESULT_DATA_ERROR;
}
len += kMatchMinLen;
do do
{ {
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
@ -638,15 +560,19 @@ int LzmaDecode(
#else #else
previousByte = outStream[nowPos - rep0]; previousByte = outStream[nowPos - rep0];
#endif #endif
outStream[nowPos++] = previousByte;
len--; len--;
outStream[nowPos++] = previousByte;
} }
while(len > 0 && nowPos < outSize); while(len != 0 && nowPos < outSize);
} }
} }
RC_NORMALIZE;
#ifdef _LZMA_OUT_READ #ifdef _LZMA_OUT_READ
vs->RangeDecoder = rd; vs->Buffer = Buffer;
vs->BufferLim = BufferLim;
vs->Range = Range;
vs->Code = Code;
vs->DictionaryPos = dictionaryPos; vs->DictionaryPos = dictionaryPos;
vs->GlobalPos = globalPos + nowPos; vs->GlobalPos = globalPos + nowPos;
vs->Reps[0] = rep0; vs->Reps[0] = rep0;
@ -654,8 +580,8 @@ int LzmaDecode(
vs->Reps[2] = rep2; vs->Reps[2] = rep2;
vs->Reps[3] = rep3; vs->Reps[3] = rep3;
vs->State = state; vs->State = state;
vs->PreviousIsMatch = previousIsMatch;
vs->RemainLen = len; vs->RemainLen = len;
vs->TempDictionary[0] = tempDictionary[0];
#endif #endif
*outSizeProcessed = nowPos; *outSizeProcessed = nowPos;

View file

@ -2,7 +2,7 @@
LzmaDecode.h LzmaDecode.h
LZMA Decoder interface 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/ http://www.7-zip.org/
LZMA SDK is licensed under two licenses: LZMA SDK is licensed under two licenses:

View 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 \ CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -Wno-trigraphs -Os \
-fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic \ -fno-strict-aliasing -fno-common -fomit-frame-pointer -G 0 -mno-abicalls -fno-pic \
-ffunction-sections -pipe -mlong-calls -fno-common \ -ffunction-sections -pipe -mlong-calls -fno-common \
-ffreestanding \
-mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap -mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
CFLAGS += -DLOADADDR=$(LOADADDR) 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) 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)),) ifneq ($(strip $(LOADER_DATA)),)
OBJECTS += data.o OBJECTS += data.o

View file

@ -121,15 +121,6 @@ static void uart_init(void)
#endif #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 * INTC routines
*/ */
@ -170,12 +161,13 @@ static void switch_init(void)
SWITCH_WRITE(SWITCH_REG_PORT4_LED, 0); SWITCH_WRITE(SWITCH_REG_PORT4_LED, 0);
} }
/*
* routines needed by decompress.c
*/
void board_putc(int ch) 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) void board_init(void)

View file

@ -1,37 +1,51 @@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define FLASH_2M (2<<20)
#define FLASH_4M (4<<20)
/* /*
* Cellvision/SparkLAN boards * Cellvision/SparkLAN boards
*/ */
#if defined(CONFIG_BOARD_CAS630) #if defined(CONFIG_BOARD_CAS630)
# define CONFIG_BOARD_NAME "CAS-630" # define CONFIG_BOARD_NAME "CAS-630"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_CAS670) #if defined(CONFIG_BOARD_CAS670)
# define CONFIG_BOARD_NAME "CAS-670" # define CONFIG_BOARD_NAME "CAS-670"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_CAS700) #if defined(CONFIG_BOARD_CAS700)
# define CONFIG_BOARD_NAME "CAS-700" # define CONFIG_BOARD_NAME "CAS-700"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_CAS790) #if defined(CONFIG_BOARD_CAS790)
# define CONFIG_BOARD_NAME "CAS-790" # define CONFIG_BOARD_NAME "CAS-790"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_CAS771) #if defined(CONFIG_BOARD_CAS771)
# define CONFIG_BOARD_NAME "CAS-771" # define CONFIG_BOARD_NAME "CAS-771"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_CAS861) #if defined(CONFIG_BOARD_CAS861)
# define CONFIG_BOARD_NAME "CAS-861" # define CONFIG_BOARD_NAME "CAS-861"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_NFS101U) #if defined(CONFIG_BOARD_NFS101U)
# define CONFIG_BOARD_NAME "NFS-101U" # define CONFIG_BOARD_NAME "NFS-101U"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_NFS202U) #if defined(CONFIG_BOARD_NFS202U)
# define CONFIG_BOARD_NAME "NFS-202U" # define CONFIG_BOARD_NAME "NFS-202U"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
/* /*
@ -39,10 +53,12 @@
*/ */
#if defined(CONFIG_BOARD_BR6104K) #if defined(CONFIG_BOARD_BR6104K)
# define CONFIG_BOARD_NAME "BR-6104K" # define CONFIG_BOARD_NAME "BR-6104K"
# define CONFIG_FLASH_SIZE FLASH_2M
#endif #endif
#if defined(CONFIG_BOARD_BR6104KP) #if defined(CONFIG_BOARD_BR6104KP)
# define CONFIG_BOARD_NAME "BR-6104KP" # define CONFIG_BOARD_NAME "BR-6104KP"
# define CONFIG_FLASH_SIZE FLASH_2M
#endif #endif
/* /*
@ -62,6 +78,7 @@
#if defined(CONFIG_BOARD_EASY83000) #if defined(CONFIG_BOARD_EASY83000)
# define CONFIG_BOARD_NAME "EASY 83000" # define CONFIG_BOARD_NAME "EASY 83000"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
/* /*
@ -69,10 +86,12 @@
*/ */
#if defined(CONFIG_BOARD_P334WT) #if defined(CONFIG_BOARD_P334WT)
# define CONFIG_BOARD_NAME "P-334WT" # define CONFIG_BOARD_NAME "P-334WT"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
#if defined(CONFIG_BOARD_P335) #if defined(CONFIG_BOARD_P335)
# define CONFIG_BOARD_NAME "P-335" # define CONFIG_BOARD_NAME "P-335"
# define CONFIG_FLASH_SIZE FLASH_4M
#endif #endif
/* /*
@ -81,3 +100,9 @@
#ifndef CONFIG_BOARD_NAME #ifndef CONFIG_BOARD_NAME
# define CONFIG_BOARD_NAME "ADM5120" # define CONFIG_BOARD_NAME "ADM5120"
#endif #endif
#ifndef CONFIG_FLASH_SIZE
# define CONFIG_FLASH_SIZE FLASH_2M
#endif
#endif /* _CONFIG_H_ */

View file

@ -1,4 +1,6 @@
/* /*
* $Id$
*
* LZMA compressed kernel decompressor for ADM5120 boards * LZMA compressed kernel decompressor for ADM5120 boards
* *
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su> * Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
@ -43,6 +45,7 @@
#include <stddef.h> #include <stddef.h>
#include "config.h" #include "config.h"
#include "printf.h"
#include "LzmaDecode.h" #include "LzmaDecode.h"
#define ADM5120_FLASH_START 0x1fc00000 /* Flash start */ #define ADM5120_FLASH_START 0x1fc00000 /* Flash start */
@ -67,6 +70,12 @@
: "r" (base), \ : "r" (base), \
"i" (op)); "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) static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
{ {
unsigned long start = KSEG0; unsigned long start = KSEG0;
@ -100,21 +109,22 @@ struct trx_header {
unsigned int offsets[3]; /* Offsets of partitions from start of 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 { struct env_var {
char *name; char *name;
char *value; 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 #ifdef CONFIG_PASS_KARGS
#define ENVV(n,v) {.name = (n), .value = (v)} #define ENVV(n,v) {.name = (n), .value = (v)}
struct env_var env_vars[] = { struct env_var env_vars[] = {
@ -123,112 +133,145 @@ struct env_var env_vars[] = {
}; };
#endif #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 char *data;
unsigned long datalen; unsigned long datalen;
typedef void (*kernel_entry)(unsigned long reg_a0, unsigned long reg_a1, static __inline__ unsigned char get_byte(void)
unsigned long reg_a2, unsigned long reg_a3);
static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
{ {
*bufferSize = 1; datalen--;
*buffer = data++; return *data++;
}
static void decompress_init(void)
{
data = _lzma_data_start;
datalen = _lzma_data_end - _lzma_data_start;
}
static int decompress_data(unsigned char *buffer, UInt32 bufferSize,
int lc, int lp, int pb, unsigned char *outStream, UInt32 outSize,
UInt32 *outSizeProcessed)
{
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 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)
{
return *(flash_base+flash_ofs++);
}
static int lzma_read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
{
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; return LZMA_RESULT_OK;
} }
static __inline__ unsigned char get_byte(void) static ILzmaInCallback lzma_callback = {
{ .Read = lzma_read_byte,
unsigned char *buffer; };
UInt32 fake;
read_byte(0, &buffer, &fake);
return *buffer;
}
static __inline__ unsigned int read_le32(void *buf) static __inline__ unsigned int read_le32(void *buf)
{ {
unsigned char *p; unsigned char *p = buf;
p = buf;
return ((unsigned int)p[0] + ((unsigned int)p[1] << 8) + return ((unsigned int)p[0] + ((unsigned int)p[1] << 8) +
((unsigned int)p[2] << 16) +((unsigned int)p[3] << 24)); ((unsigned int)p[2] << 16) +((unsigned int)p[3] << 24));
} }
static void print_char(char ch) static void decompress_init(void)
{ {
if (ch == '\n') struct trx_header *hdr = NULL;
board_putc('\r'); unsigned long kofs,klen;
board_putc(ch);
}
static void print_str(char * str) printf("Looking for TRX header... ");
{
while ( *str != 0 )
print_char(*str++);
}
static void print_hex(int val)
{
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);
}
}
#if !(LZMA_WRAPPER)
static unsigned char *find_kernel(void)
{
struct trx_header *hdr;
unsigned char *ret;
print_str("Looking for TRX header... ");
/* look for trx header, 32-bit data access */ /* look for trx header, 32-bit data access */
hdr = NULL; for (flash_ofs = 0; flash_ofs < FLASH_BANK_SIZE; flash_ofs += TRX_ALIGN) {
for (ret = ((unsigned char *) KSEG1ADDR(ADM5120_FLASH_START)); if (read_le32(&flash_base[flash_ofs]) == TRX_MAGIC) {
ret < ((unsigned char *)KSEG1ADDR(ADM5120_FLASH_END)); hdr = (struct trx_header *)&flash_base[flash_ofs];
ret += TRX_ALIGN) {
if (read_le32(ret) == TRX_MAGIC) {
hdr = (struct trx_header *)ret;
break; break;
} }
} }
if (hdr == NULL) { if (hdr == NULL) {
print_str("not found!\n"); printf("not found!\n");
return NULL; /* 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 */ /* compressed kernel is in the partition 0 or 1 */
if ((read_le32(&hdr->offsets[1]) == 0) || kofs = read_le32(&hdr->offsets[1]);
(read_le32(&hdr->offsets[1]) > 65536)) { if (kofs == 0 || kofs > 65536) {
ret += read_le32(&hdr->offsets[0]); klen = kofs-read_le32(&hdr->offsets[0]);
print_str("0\n"); kofs = read_le32(&hdr->offsets[0]);
} else { } else {
ret += read_le32(&hdr->offsets[1]); klen = read_le32(&hdr->offsets[2]);
print_str("1\n"); 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;
}
static int decompress_data(unsigned char *buffer, UInt32 bufferSize,
int lc, int lp, int pb, unsigned char *outStream, UInt32 outSize,
UInt32 *outSizeProcessed)
{
return LzmaDecode(buffer, bufferSize, lc, lp, pb, &lzma_callback,
outStream, outSize, outSizeProcessed);
} }
#endif /* !(LZMA_WRAPPER) */ #endif /* !(LZMA_WRAPPER) */
static void halt(void)
{
print_str("\nSystem halted!\n");
for(;;);
}
/* should be the first function */ /* should be the first function */
void decompress_entry(unsigned long reg_a0, unsigned long reg_a1, void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
unsigned long reg_a2, unsigned long reg_a3, unsigned long reg_a2, unsigned long reg_a3,
@ -241,27 +284,13 @@ void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
unsigned int pb; /* pos state bits */ unsigned int pb; /* pos state bits */
unsigned int osize; /* uncompressed size */ unsigned int osize; /* uncompressed size */
int res; int res;
#if !(LZMA_WRAPPER)
ILzmaInCallback callback;
#endif
board_init(); 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"); ", Copyright (C) 2007 OpenWrt.org\n\n");
#if LZMA_WRAPPER decompress_init();
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
/* lzma args */ /* lzma args */
i = get_byte(); i = get_byte();
@ -282,41 +311,32 @@ void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
get_byte(); get_byte();
print_str("decompressing kernel... "); printf("decompressing kernel... ");
/* decompress kernel */ /* decompress kernel */
#if LZMA_WRAPPER res = decompress_data(workspace, ~0, lc, lp, pb,
res = LzmaDecode(workspace, ~0, lc, lp, pb, data, datalen, (unsigned char *)LOADADDR, osize, &i);
(unsigned char*)LOADADDR, osize, &i);
#else
callback.Read = read_byte;
res = LzmaDecode(workspace, ~0, lc, lp, pb, &callback,
(unsigned char*)LOADADDR, osize, &i);
#endif
if (res != LZMA_RESULT_OK) { if (res != LZMA_RESULT_OK) {
print_str("failed!\n"); printf("failed, ");
print_str("LzmaDecode: ");
switch (res) { switch (res) {
case LZMA_RESULT_DATA_ERROR: case LZMA_RESULT_DATA_ERROR:
print_str("data error\n"); printf("data error!\n");
break; break;
case LZMA_RESULT_NOT_ENOUGH_MEM: case LZMA_RESULT_NOT_ENOUGH_MEM:
print_str("not enough memory\n"); printf("not enough memory!\n");
break; break;
default: default:
print_str("unknown error, err=0x"); printf("unknown error %d!\n", res);
print_hex(res);
print_str("\n");
} }
halt(); halt();
} } else
printf("done!\n");
print_str("done!\n");
blast_dcache(dcache_size, dcache_lsize); blast_dcache(dcache_size, dcache_lsize);
blast_icache(icache_size, icache_lsize); blast_icache(icache_size, icache_lsize);
print_str("launching kernel...\n\n"); printf("launching kernel...\n\n");
#ifdef CONFIG_PASS_KARGS #ifdef CONFIG_PASS_KARGS
reg_a0 = 0; reg_a0 = 0;

View file

@ -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);
}

View file

@ -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_ */