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
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.
*/
@ -32,242 +32,44 @@
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
typedef struct _CRangeDecoder
{
Byte *Buffer;
Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#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
ILzmaInCallback *InCallback;
int Result;
#endif
int ExtraBytes;
} CRangeDecoder;
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_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 ReadByte (*rd->Buffer++) */
#define ReadByte (RangeDecoderReadByte(rd))
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
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_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_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
{
RC_INIT_VAR
UInt32 result = 0;
int i;
for (i = numTotalBits; i > 0; i--)
{
/* UInt32 t; */
range >>= 1;
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
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;
}
#endif
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_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
#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 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_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
{ UpdateBit0(p); mi <<= 1; A0; } else \
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
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_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
RC_INIT;
#else
inStream, inSize
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
RC_INIT;
#else
inStream, inSize
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)
}
else
previousByte = LzmaLiteralDecode(probs, &rd);
while (symbol < 0x100);
// prob -= 0x100;
}
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
{
if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
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
if (
(nowPos
UpdateBit0(prob);
if (nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
== 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;
}
{
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))
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;

View 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:

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 \
-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

View 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)

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
*/
#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
/*
@ -39,10 +53,12 @@
*/
#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
/*
@ -69,10 +86,12 @@
*/
#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
/*
@ -81,3 +100,9 @@
#ifndef CONFIG_BOARD_NAME
# define CONFIG_BOARD_NAME "ADM5120"
#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
*
* 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 */
@ -67,6 +70,12 @@
: "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,112 +133,145 @@ 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++;
datalen--;
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;
}
static __inline__ unsigned char get_byte(void)
{
unsigned char *buffer;
UInt32 fake;
read_byte(0, &buffer, &fake);
return *buffer;
}
static ILzmaInCallback lzma_callback = {
.Read = lzma_read_byte,
};
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) +
((unsigned int)p[2] << 16) +((unsigned int)p[3] << 24));
}
static void print_char(char ch)
static void decompress_init(void)
{
if (ch == '\n')
board_putc('\r');
board_putc(ch);
}
struct trx_header *hdr = NULL;
unsigned long kofs,klen;
static void print_str(char * str)
{
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... ");
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;
}
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) */
static void halt(void)
{
print_str("\nSystem halted!\n");
for(;;);
}
/* should be the first function */
void decompress_entry(unsigned long reg_a0, unsigned long reg_a1,
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 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,
res = decompress_data(workspace, ~0, lc, lp, pb,
(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) {
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;

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