OpenWrt

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 3  →  ?path2? @ 4
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/LzmaDecode.c
@@ -0,0 +1,663 @@
/*
LzmaDecode.c
LZMA Decoder
LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
http://www.7-zip.org/
 
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
 
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this code, expressly permits you to
statically or dynamically link your code (or bind by name) to the
interfaces of this file without subjecting your linked code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
 
#include "LzmaDecode.h"
 
#ifndef Byte
#define Byte unsigned char
#endif
 
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
 
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
 
typedef struct _CRangeDecoder
{
Byte *Buffer;
Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#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 ReadByte (*rd->Buffer++) */
#define ReadByte (RangeDecoderReadByte(rd))
 
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; }
 
UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
{
RC_INIT_VAR
UInt32 result = 0;
int i;
for (i = numTotalBits; i > 0; i--)
{
/* UInt32 t; */
range >>= 1;
 
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;
}
 
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_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_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
 
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);
}
 
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;
}
 
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)
 
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
 
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
 
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 kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
 
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
 
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
 
#define kMatchMinLen 2
 
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
 
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
 
#ifdef _LZMA_OUT_READ
 
typedef struct _LzmaVarState
{
CRangeDecoder RangeDecoder;
Byte *Dictionary;
UInt32 DictionarySize;
UInt32 DictionaryPos;
UInt32 GlobalPos;
UInt32 Reps[4];
int lc;
int lp;
int pb;
int State;
int PreviousIsMatch;
int RemainLen;
} LzmaVarState;
 
int LzmaDecoderInit(
unsigned char *buffer, UInt32 bufferSize,
int lc, int lp, int pb,
unsigned char *dictionary, UInt32 dictionarySize,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback
#else
unsigned char *inStream, UInt32 inSize
#endif
)
{
LzmaVarState *vs = (LzmaVarState *)buffer;
CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
UInt32 i;
if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
return LZMA_RESULT_NOT_ENOUGH_MEM;
vs->Dictionary = dictionary;
vs->DictionarySize = dictionarySize;
vs->DictionaryPos = 0;
vs->GlobalPos = 0;
vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
vs->lc = lc;
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
);
return LZMA_RESULT_OK;
}
 
int LzmaDecode(unsigned char *buffer,
unsigned char *outStream, UInt32 outSize,
UInt32 *outSizeProcessed)
{
LzmaVarState *vs = (LzmaVarState *)buffer;
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;
UInt32 posStateMask = (1 << (vs->pb)) - 1;
UInt32 literalPosMask = (1 << (vs->lp)) - 1;
int lc = vs->lc;
int len = vs->RemainLen;
UInt32 globalPos = vs->GlobalPos;
 
Byte *dictionary = vs->Dictionary;
UInt32 dictionarySize = vs->DictionarySize;
UInt32 dictionaryPos = vs->DictionaryPos;
 
if (len == -1)
{
*outSizeProcessed = 0;
return LZMA_RESULT_OK;
}
 
while(len > 0 && nowPos < outSize)
{
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
len--;
}
if (dictionaryPos == 0)
previousByte = dictionary[dictionarySize - 1];
else
previousByte = dictionary[dictionaryPos - 1];
#else
 
int LzmaDecode(
Byte *buffer, UInt32 bufferSize,
int lc, int lp, int pb,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback,
#else
unsigned char *inStream, UInt32 inSize,
#endif
unsigned char *outStream, UInt32 outSize,
UInt32 *outSizeProcessed)
{
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;
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
);
#endif
 
*outSizeProcessed = 0;
while(nowPos < outSize)
{
int posState = (int)(
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#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)
{
CProb *probs = p + Literal + (LZMA_LIT_SIZE *
(((
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
 
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
if (previousIsMatch)
{
Byte matchByte;
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
matchByte = dictionary[pos];
#else
matchByte = outStream[nowPos - rep0];
#endif
previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
previousIsMatch = 0;
}
else
previousByte = LzmaLiteralDecode(probs, &rd);
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#endif
}
else
{
previousIsMatch = 1;
if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
{
if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
{
if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
{
#ifdef _LZMA_OUT_READ
UInt32 pos;
#endif
if (
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
== 0)
return LZMA_RESULT_DATA_ERROR;
state = state < 7 ? 9 : 11;
#ifdef _LZMA_OUT_READ
pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
outStream[nowPos++] = previousByte;
continue;
}
}
else
{
UInt32 distance;
if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
distance = rep1;
else
{
if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
distance = rep2;
else
{
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
state = state < 7 ? 8 : 11;
}
else
{
int posSlot;
rep3 = rep2;
rep2 = rep1;
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);
rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
if (posSlot < kEndPosModelIndex)
{
rep0 += RangeDecoderReverseBitTreeDecode(
p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
}
else
{
rep0 += RangeDecoderDecodeDirectBits(&rd,
numDirectBits - kNumAlignBits) << kNumAlignBits;
rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
}
}
else
rep0 = posSlot;
rep0++;
}
if (rep0 == (UInt32)(0))
{
/* it's for stream version */
len = -1;
break;
}
if (rep0 > nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
{
return LZMA_RESULT_DATA_ERROR;
}
len += kMatchMinLen;
do
{
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
outStream[nowPos++] = previousByte;
len--;
}
while(len > 0 && nowPos < outSize);
}
}
 
#ifdef _LZMA_OUT_READ
vs->RangeDecoder = rd;
vs->DictionaryPos = dictionaryPos;
vs->GlobalPos = globalPos + nowPos;
vs->Reps[0] = rep0;
vs->Reps[1] = rep1;
vs->Reps[2] = rep2;
vs->Reps[3] = rep3;
vs->State = state;
vs->PreviousIsMatch = previousIsMatch;
vs->RemainLen = len;
#endif
 
*outSizeProcessed = nowPos;
return LZMA_RESULT_OK;
}
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/LzmaDecode.h
@@ -0,0 +1,100 @@
/*
LzmaDecode.h
LZMA Decoder interface
 
LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
http://www.7-zip.org/
 
LZMA SDK is licensed under two licenses:
1) GNU Lesser General Public License (GNU LGPL)
2) Common Public License (CPL)
It means that you can select one of these two licenses and
follow rules of that license.
 
SPECIAL EXCEPTION:
Igor Pavlov, as the author of this code, expressly permits you to
statically or dynamically link your code (or bind by name) to the
interfaces of this file without subjecting your linked code to the
terms of the CPL or GNU LGPL. Any modifications or additions
to this file, however, are subject to the LGPL or CPL terms.
*/
 
#ifndef __LZMADECODE_H
#define __LZMADECODE_H
 
/* #define _LZMA_IN_CB */
/* Use callback for input data */
 
/* #define _LZMA_OUT_READ */
/* Use read function for output data */
 
/* #define _LZMA_PROB32 */
/* It can increase speed on some 32-bit CPUs,
but memory usage will be doubled in that case */
 
/* #define _LZMA_LOC_OPT */
/* Enable local speed optimizations inside code */
 
#ifndef UInt32
#ifdef _LZMA_UINT32_IS_ULONG
#define UInt32 unsigned long
#else
#define UInt32 unsigned int
#endif
#endif
 
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb unsigned short
#endif
 
#define LZMA_RESULT_OK 0
#define LZMA_RESULT_DATA_ERROR 1
#define LZMA_RESULT_NOT_ENOUGH_MEM 2
 
#ifdef _LZMA_IN_CB
typedef struct _ILzmaInCallback
{
int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
} ILzmaInCallback;
#endif
 
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
 
/*
bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
bufferSize += 100 in case of _LZMA_OUT_READ
by default CProb is unsigned short,
but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
*/
 
#ifdef _LZMA_OUT_READ
int LzmaDecoderInit(
unsigned char *buffer, UInt32 bufferSize,
int lc, int lp, int pb,
unsigned char *dictionary, UInt32 dictionarySize,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback
#else
unsigned char *inStream, UInt32 inSize
#endif
);
#endif
 
int LzmaDecode(
unsigned char *buffer,
#ifndef _LZMA_OUT_READ
UInt32 bufferSize,
int lc, int lp, int pb,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback,
#else
unsigned char *inStream, UInt32 inSize,
#endif
#endif
unsigned char *outStream, UInt32 outSize,
UInt32 *outSizeProcessed);
 
#endif
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/Makefile
@@ -0,0 +1,78 @@
#
# Makefile for Broadcom BCM947XX boards
#
# Copyright 2001-2003, Broadcom Corporation
# All Rights Reserved.
#
# THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
# KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
# SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
#
# Copyright 2004 Manuel Novoa III <mjn3@codepoet.org>
# Modified to support bzip'd kernels.
# Of course, it would be better to integrate bunzip capability into CFE.
#
# Copyright 2005 Oleg I. Vdovikin <oleg@cs.msu.su>
# Cleaned up, modified for lzma support, removed from kernel
#
 
TEXT_START := 0x80001000
BZ_TEXT_START := 0x80600000
BZ_STACK_START := 0x80700000
 
OBJCOPY := $(CROSS_COMPILE)objcopy -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 \
-mabi=32 -march=mips32 -Wa,-32 -Wa,-march=mips32 -Wa,-mips32 -Wa,--trap
CFLAGS += -DLOADADDR=$(TEXT_START) -D_LZMA_IN_CB
 
ASFLAGS = $(CFLAGS) -D__ASSEMBLY__ -DBZ_TEXT_START=$(BZ_TEXT_START) -DBZ_STACK_START=$(BZ_STACK_START)
 
SEDFLAGS := s/BZ_TEXT_START/$(BZ_TEXT_START)/;s/BZ_STACK_START/$(BZ_STACK_START)/;s/TEXT_START/$(TEXT_START)/
 
OBJECTS := head.o data.o
 
all: loader.gz loader.elf
 
# Don't build dependencies, this may die if $(CC) isn't gcc
dep:
 
install:
 
loader.gz: loader
gzip -nc9 $< > $@
 
loader.elf: loader.o
cp $< $@
 
loader: loader.o
$(OBJCOPY) $< $@
 
loader.o: loader.lds $(OBJECTS)
$(LD) -static --gc-sections -no-warn-mismatch -T loader.lds -o $@ $(OBJECTS)
 
loader.lds: loader.lds.in Makefile
@sed "$(SEDFLAGS)" < $< > $@
 
data.o: data.lds decompress.image
$(LD) -no-warn-mismatch -T data.lds -r -o $@ -b binary decompress.image -b elf32-tradlittlemips
 
data.lds:
@echo "SECTIONS { .data : { code_start = .; *(.data) code_stop = .; }}" > $@
 
decompress.image: decompress
$(OBJCOPY) $< $@
 
decompress: decompress.lds decompress.o LzmaDecode.o
$(LD) -static --gc-sections -no-warn-mismatch -T decompress.lds -o $@ decompress.o LzmaDecode.o
 
decompress.lds: decompress.lds.in Makefile
@sed "$(SEDFLAGS)" < $< > $@
 
mrproper: clean
 
clean:
rm -f loader.gz loader decompress *.lds *.o *.image
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/README
@@ -0,0 +1,55 @@
/*
* LZMA compressed kernel decompressor for bcm947xx boards
*
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
The code is intended to decompress kernel, being compressed using lzma utility
build using 7zip LZMA SDK. This utility is located in the LZMA_Alone directory
 
decompressor code expects that your .trx file consist of three partitions:
 
1) decompressor itself (this is gziped code which pmon/cfe will extract and run
on boot-up instead of real kernel)
2) LZMA compressed kernel (both streamed and regular modes are supported now)
3) Root filesystem
 
Please be sure to apply the following patch for use this new trx layout (it will
allow using both new and old trx files for root filesystem lookup code)
 
--- linuz/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:24:27.503322896 +0300
+++ linux/arch/mips/brcm-boards/bcm947xx/setup.c 2005-01-23 19:29:05.237100944 +0300
@@ -221,7 +221,9 @@
/* Try looking at TRX header for rootfs offset */
if (le32_to_cpu(trx->magic) == TRX_MAGIC) {
bcm947xx_parts[1].offset = off;
- if (le32_to_cpu(trx->offsets[1]) > off)
+ if (le32_to_cpu(trx->offsets[2]) > off)
+ off = le32_to_cpu(trx->offsets[2]);
+ else if (le32_to_cpu(trx->offsets[1]) > off)
off = le32_to_cpu(trx->offsets[1]);
continue;
}
 
 
Revision history:
0.02 Initial release
0.03 Added Mineharu Takahara <mtakahar@yahoo.com> patch to pass actual
output size to decoder (stream mode compressed input is not
a requirement anymore)
0.04 Reordered functions using lds script
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/decompress.c
@@ -0,0 +1,186 @@
/*
* LZMA compressed kernel decompressor for bcm947xx boards
*
* Copyright (C) 2005 by Oleg I. Vdovikin <oleg@cs.msu.su>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Please note, this was code based on the bunzip2 decompressor code
* by Manuel Novoa III (mjn3@codepoet.org), although the only thing left
* is an idea and part of original vendor code
*
*
* 12-Mar-2005 Mineharu Takahara <mtakahar@yahoo.com>
* pass actual output size to decoder (stream mode
* compressed input is not a requirement anymore)
*
* 24-Apr-2005 Oleg I. Vdovikin
* reordered functions using lds script, removed forward decl
*
*/
 
#include "LzmaDecode.h"
 
#define BCM4710_FLASH 0x1fc00000 /* Flash */
 
#define KSEG0 0x80000000
#define KSEG1 0xa0000000
 
#define KSEG1ADDR(a) ((((unsigned)(a)) & 0x1fffffffU) | KSEG1)
 
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
 
#define cache_unroll(base,op) \
__asm__ __volatile__( \
".set noreorder;\n" \
".set mips3;\n" \
"cache %1, (%0);\n" \
".set mips0;\n" \
".set reorder\n" \
: \
: "r" (base), \
"i" (op));
 
static __inline__ void blast_icache(unsigned long size, unsigned long lsize)
{
unsigned long start = KSEG0;
unsigned long end = (start + size);
 
while(start < end) {
cache_unroll(start,Index_Invalidate_I);
start += lsize;
}
}
 
static __inline__ void blast_dcache(unsigned long size, unsigned long lsize)
{
unsigned long start = KSEG0;
unsigned long end = (start + size);
 
while(start < end) {
cache_unroll(start,Index_Writeback_Inv_D);
start += lsize;
}
}
 
#define TRX_MAGIC 0x30524448 /* "HDR0" */
 
struct trx_header {
unsigned int magic; /* "HDR0" */
unsigned int len; /* Length of file including header */
unsigned int crc32; /* 32-bit CRC from flag_version to end of file */
unsigned int flag_version; /* 0:15 flags, 16:31 version */
unsigned int offsets[3]; /* Offsets of partitions from start of header */
};
 
#define EDIMAX_PS_HEADER_MAGIC 0x36315350 /* "PS16" */
#define EDIMAX_PS_HEADER_LEN 0xc /* 12 bytes long for edimax header */
 
/* beyound the image end, size not known in advance */
extern unsigned char workspace[];
 
unsigned int offset;
unsigned char *data;
 
/* flash access should be aligned, so wrapper is used */
/* read byte from the flash, all accesses are 32-bit aligned */
static int read_byte(void *object, unsigned char **buffer, UInt32 *bufferSize)
{
static unsigned int val;
 
if (((unsigned int)offset % 4) == 0) {
val = *(unsigned int *)data;
data += 4;
}
*bufferSize = 1;
*buffer = ((unsigned char *)&val) + (offset++ & 3);
return LZMA_RESULT_OK;
}
 
static __inline__ unsigned char get_byte(void)
{
unsigned char *buffer;
UInt32 fake;
return read_byte(0, &buffer, &fake), *buffer;
}
 
/* should be the first function */
void entry(unsigned long icache_size, unsigned long icache_lsize,
unsigned long dcache_size, unsigned long dcache_lsize,
unsigned long fw_arg0, unsigned long fw_arg1,
unsigned long fw_arg2, unsigned long fw_arg3)
{
unsigned int i; /* temp value */
unsigned int lc; /* literal context bits */
unsigned int lp; /* literal pos state bits */
unsigned int pb; /* pos state bits */
unsigned int osize; /* uncompressed size */
 
ILzmaInCallback callback;
callback.Read = read_byte;
 
/* look for trx header, 32-bit data access */
for (data = ((unsigned char *) KSEG1ADDR(BCM4710_FLASH));
((struct trx_header *)data)->magic != TRX_MAGIC &&
((struct trx_header *)data)->magic != EDIMAX_PS_HEADER_MAGIC;
data += 65536);
 
if (((struct trx_header *)data)->magic == EDIMAX_PS_HEADER_MAGIC)
data += EDIMAX_PS_HEADER_LEN;
/* compressed kernel is in the partition 0 or 1 */
if (((struct trx_header *)data)->offsets[1] > 65536)
data += ((struct trx_header *)data)->offsets[0];
else
data += ((struct trx_header *)data)->offsets[1];
 
offset = 0;
 
/* lzma args */
i = get_byte();
lc = i % 9, i = i / 9;
lp = i % 5, pb = i / 5;
 
/* skip rest of the LZMA coder property */
for (i = 0; i < 4; i++)
get_byte();
 
/* read the lower half of uncompressed size in the header */
osize = ((unsigned int)get_byte()) +
((unsigned int)get_byte() << 8) +
((unsigned int)get_byte() << 16) +
((unsigned int)get_byte() << 24);
 
/* skip rest of the header (upper half of uncompressed size) */
for (i = 0; i < 4; i++)
get_byte();
 
/* decompress kernel */
if (LzmaDecode(workspace, ~0, lc, lp, pb, &callback,
(unsigned char*)LOADADDR, osize, &i) == LZMA_RESULT_OK)
{
blast_dcache(dcache_size, dcache_lsize);
blast_icache(icache_size, icache_lsize);
 
/* Jump to load address */
((void (*)(unsigned long, unsigned long, unsigned long,
unsigned long)) LOADADDR)(fw_arg0, fw_arg1, fw_arg2,
fw_arg3);
}
}
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/decompress.lds.in
@@ -0,0 +1,20 @@
OUTPUT_ARCH(mips)
ENTRY(entry)
SECTIONS {
. = BZ_TEXT_START;
.text : {
*(.text.entry)
*(.text)
*(.rodata)
}
 
.data : {
*(.data)
}
 
.bss : {
*(.bss)
}
 
workspace = .;
}
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/head.S
@@ -0,0 +1,161 @@
/* Copyright 2005 Oleg I. Vdovikin (oleg@cs.msu.su) */
/* cache manipulation adapted from Broadcom code */
/* idea taken from original bunzip2 decompressor code */
/* Copyright 2004 Manuel Novoa III (mjn3@codepoet.org) */
/* Licensed under the linux kernel's version of the GPL.*/
 
#include <asm/asm.h>
#include <asm/regdef.h>
 
#define KSEG0 0x80000000
 
#define C0_CONFIG $16
#define C0_TAGLO $28
#define C0_TAGHI $29
 
#define CONF1_DA_SHIFT 7 /* D$ associativity */
#define CONF1_DA_MASK 0x00000380
#define CONF1_DA_BASE 1
#define CONF1_DL_SHIFT 10 /* D$ line size */
#define CONF1_DL_MASK 0x00001c00
#define CONF1_DL_BASE 2
#define CONF1_DS_SHIFT 13 /* D$ sets/way */
#define CONF1_DS_MASK 0x0000e000
#define CONF1_DS_BASE 64
#define CONF1_IA_SHIFT 16 /* I$ associativity */
#define CONF1_IA_MASK 0x00070000
#define CONF1_IA_BASE 1
#define CONF1_IL_SHIFT 19 /* I$ line size */
#define CONF1_IL_MASK 0x00380000
#define CONF1_IL_BASE 2
#define CONF1_IS_SHIFT 22 /* Instruction cache sets/way */
#define CONF1_IS_MASK 0x01c00000
#define CONF1_IS_BASE 64
 
#define Index_Invalidate_I 0x00
#define Index_Writeback_Inv_D 0x01
 
.text
LEAF(startup)
.set noreorder
li sp, BZ_STACK_START
addi sp, -48
sw a0, 16(sp)
sw a1, 20(sp)
sw a2, 24(sp)
sw a3, 28(sp)
 
/* Copy decompressor code to the right place */
li t2, BZ_TEXT_START
add a0, t2, 0
la a1, code_start
la a2, code_stop
$L1:
lw t0, 0(a1)
sw t0, 0(a0)
add a1, 4
add a0, 4
blt a1, a2, $L1
nop
 
/* At this point we need to invalidate dcache and */
/* icache before jumping to new code */
 
1: /* Get cache sizes */
.set mips32
mfc0 s0,C0_CONFIG,1
.set mips0
 
li s1,CONF1_DL_MASK
and s1,s0
beq s1,zero,nodc
nop
 
srl s1,CONF1_DL_SHIFT
li t0,CONF1_DL_BASE
sll s1,t0,s1 /* s1 has D$ cache line size */
 
li s2,CONF1_DA_MASK
and s2,s0
srl s2,CONF1_DA_SHIFT
addiu s2,CONF1_DA_BASE /* s2 now has D$ associativity */
 
li t0,CONF1_DS_MASK
and t0,s0
srl t0,CONF1_DS_SHIFT
li s3,CONF1_DS_BASE
sll s3,s3,t0 /* s3 has D$ sets per way */
 
multu s2,s3 /* sets/way * associativity */
mflo t0 /* total cache lines */
 
multu s1,t0 /* D$ linesize * lines */
mflo s2 /* s2 is now D$ size in bytes */
 
/* Initilize the D$: */
mtc0 zero,C0_TAGLO
mtc0 zero,C0_TAGHI
 
li t0,KSEG0 /* Just an address for the first $ line */
addu t1,t0,s2 /* + size of cache == end */
 
.set mips3
1: cache Index_Writeback_Inv_D,0(t0)
.set mips0
bne t0,t1,1b
addu t0,s1
 
nodc:
/* Now we get to do it all again for the I$ */
 
move s3,zero /* just in case there is no icache */
move s4,zero
 
li t0,CONF1_IL_MASK
and t0,s0
beq t0,zero,noic
nop
 
srl t0,CONF1_IL_SHIFT
li s3,CONF1_IL_BASE
sll s3,t0 /* s3 has I$ cache line size */
 
li t0,CONF1_IA_MASK
and t0,s0
srl t0,CONF1_IA_SHIFT
addiu s4,t0,CONF1_IA_BASE /* s4 now has I$ associativity */
 
li t0,CONF1_IS_MASK
and t0,s0
srl t0,CONF1_IS_SHIFT
li s5,CONF1_IS_BASE
sll s5,t0 /* s5 has I$ sets per way */
 
multu s4,s5 /* sets/way * associativity */
mflo t0 /* s4 is now total cache lines */
 
multu s3,t0 /* I$ linesize * lines */
mflo s4 /* s4 is cache size in bytes */
 
/* Initilize the I$: */
mtc0 zero,C0_TAGLO
mtc0 zero,C0_TAGHI
 
li t0,KSEG0 /* Just an address for the first $ line */
addu t1,t0,s4 /* + size of cache == end */
 
.set mips3
1: cache Index_Invalidate_I,0(t0)
.set mips0
bne t0,t1,1b
addu t0,s3
 
noic:
move a0,s4 /* icache size */
move a1,s3 /* icache line size */
move a2,s2 /* dcache size */
jal t2
move a3,s1 /* dcache line size */
 
.set reorder
END(startup)
/branches/gl-inet/target/linux/brcm47xx/image/lzma-loader/src/loader.lds.in
@@ -0,0 +1,17 @@
OUTPUT_ARCH(mips)
ENTRY(startup)
SECTIONS {
. = TEXT_START;
.text : {
*(.text)
*(.rodata)
}
 
.data : {
*(.data)
}
 
.bss : {
*(.bss)
}
}