Added LZMA support to CILO.

master
Philippe Vachon 16 years ago
parent b918c0b1b8
commit 8e37b13a4f

@ -0,0 +1,584 @@
/*
LzmaDecode.c
LZMA Decoder (optimized for Speed version)
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
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"
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_READ_BYTE (*Buffer++)
#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
{ int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
#ifdef _LZMA_IN_CB
#define RC_TEST { if (Buffer == BufferLim) \
{ SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
#else
#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
#endif
#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
{ UpdateBit0(p); mi <<= 1; A0; } else \
{ UpdateBit1(p); mi = (mi + mi) + 1; A1; }
#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
{ int i = numLevels; res = 1; \
do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
res -= (1 << numLevels); }
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
{
unsigned char prop0;
if (size < LZMA_PROPERTIES_SIZE)
return LZMA_RESULT_DATA_ERROR;
prop0 = propsData[0];
if (prop0 >= (9 * 5 * 5))
return LZMA_RESULT_DATA_ERROR;
{
for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
propsRes->lc = prop0;
/*
unsigned char remainder = (unsigned char)(prop0 / 9);
propsRes->lc = prop0 % 9;
propsRes->pb = remainder / 5;
propsRes->lp = remainder % 5;
*/
}
#ifdef _LZMA_OUT_READ
{
int i;
propsRes->DictionarySize = 0;
for (i = 0; i < 4; i++)
propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
if (propsRes->DictionarySize == 0)
propsRes->DictionarySize = 1;
}
#endif
return LZMA_RESULT_OK;
}
#define kLzmaStreamWasFinishedId (-1)
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *InCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
{
CProb *p = vs->Probs;
SizeT nowPos = 0;
Byte previousByte = 0;
UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
int lc = vs->Properties.lc;
#ifdef _LZMA_OUT_READ
UInt32 Range = vs->Range;
UInt32 Code = vs->Code;
#ifdef _LZMA_IN_CB
const Byte *Buffer = vs->Buffer;
const Byte *BufferLim = vs->BufferLim;
#else
const Byte *Buffer = inStream;
const Byte *BufferLim = inStream + inSize;
#endif
int state = vs->State;
UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
int len = vs->RemainLen;
UInt32 globalPos = vs->GlobalPos;
UInt32 distanceLimit = vs->DistanceLimit;
Byte *dictionary = vs->Dictionary;
UInt32 dictionarySize = vs->Properties.DictionarySize;
UInt32 dictionaryPos = vs->DictionaryPos;
Byte tempDictionary[4];
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
if (len == kLzmaStreamWasFinishedId)
return LZMA_RESULT_OK;
if (dictionarySize == 0)
{
dictionary = tempDictionary;
dictionarySize = 1;
tempDictionary[0] = vs->TempDictionary[0];
}
if (len == kLzmaNeedInitId)
{
{
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
UInt32 i;
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
rep0 = rep1 = rep2 = rep3 = 1;
state = 0;
globalPos = 0;
distanceLimit = 0;
dictionaryPos = 0;
dictionary[dictionarySize - 1] = 0;
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
}
len = 0;
}
while(len != 0 && nowPos < outSize)
{
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
len--;
}
if (dictionaryPos == 0)
previousByte = dictionary[dictionarySize - 1];
else
previousByte = dictionary[dictionaryPos - 1];
#else /* if !_LZMA_OUT_READ */
int state = 0;
UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
int len = 0;
const Byte *Buffer;
const Byte *BufferLim;
UInt32 Range;
UInt32 Code;
#ifndef _LZMA_IN_CB
*inSizeProcessed = 0;
#endif
*outSizeProcessed = 0;
{
UInt32 i;
UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
for (i = 0; i < numProbs; i++)
p[i] = kBitModelTotal >> 1;
}
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
#endif /* _LZMA_OUT_READ */
while(nowPos < outSize)
{
CProb *prob;
UInt32 bound;
int posState = (int)(
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& posStateMask);
prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
int symbol = 1;
UpdateBit0(prob)
prob = p + Literal + (LZMA_LIT_SIZE *
(((
(nowPos
#ifdef _LZMA_OUT_READ
+ globalPos
#endif
)
& literalPosMask) << lc) + (previousByte >> (8 - lc))));
if (state >= kNumLitStates)
{
int matchByte;
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
matchByte = dictionary[pos];
#else
matchByte = outStream[nowPos - rep0];
#endif
do
{
int bit;
CProb *probLit;
matchByte <<= 1;
bit = (matchByte & 0x100);
probLit = prob + 0x100 + bit + symbol;
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
}
while (symbol < 0x100);
}
while (symbol < 0x100)
{
CProb *probLit = prob + symbol;
RC_GET_BIT(probLit, symbol)
}
previousByte = (Byte)symbol;
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#endif
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
}
else
{
UpdateBit1(prob);
prob = p + IsRep + state;
IfBit0(prob)
{
UpdateBit0(prob);
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
state = state < kNumLitStates ? 0 : 3;
prob = p + LenCoder;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG0 + state;
IfBit0(prob)
{
UpdateBit0(prob);
prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
IfBit0(prob)
{
#ifdef _LZMA_OUT_READ
UInt32 pos;
#endif
UpdateBit0(prob);
#ifdef _LZMA_OUT_READ
if (distanceLimit == 0)
#else
if (nowPos == 0)
#endif
return LZMA_RESULT_DATA_ERROR;
state = state < kNumLitStates ? 9 : 11;
#ifdef _LZMA_OUT_READ
pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
if (distanceLimit < dictionarySize)
distanceLimit++;
#endif
continue;
}
else
{
UpdateBit1(prob);
}
}
else
{
UInt32 distance;
UpdateBit1(prob);
prob = p + IsRepG1 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep1;
}
else
{
UpdateBit1(prob);
prob = p + IsRepG2 + state;
IfBit0(prob)
{
UpdateBit0(prob);
distance = rep2;
}
else
{
UpdateBit1(prob);
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
state = state < kNumLitStates ? 8 : 11;
prob = p + RepLenCoder;
}
{
int numBits, offset;
CProb *probLen = prob + LenChoice;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0;
numBits = kLenNumLowBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenChoice2;
IfBit0(probLen)
{
UpdateBit0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols;
numBits = kLenNumMidBits;
}
else
{
UpdateBit1(probLen);
probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols;
numBits = kLenNumHighBits;
}
}
RangeDecoderBitTreeDecode(probLen, numBits, len);
len += offset;
}
if (state < 4)
{
int posSlot;
state += kNumLitStates;
prob = p + PosSlot +
((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
kNumPosSlotBits);
RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
if (posSlot >= kStartPosModelIndex)
{
int numDirectBits = ((posSlot >> 1) - 1);
rep0 = (2 | ((UInt32)posSlot & 1));
if (posSlot < kEndPosModelIndex)
{
rep0 <<= numDirectBits;
prob = p + SpecPos + rep0 - posSlot - 1;
}
else
{
numDirectBits -= kNumAlignBits;
do
{
RC_NORMALIZE
Range >>= 1;
rep0 <<= 1;
if (Code >= Range)
{
Code -= Range;
rep0 |= 1;
}
}
while (--numDirectBits != 0);
prob = p + Align;
rep0 <<= kNumAlignBits;
numDirectBits = kNumAlignBits;
}
{
int i = 1;
int mi = 1;
do
{
CProb *prob3 = prob + mi;
RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
i <<= 1;
}
while(--numDirectBits != 0);
}
}
else
rep0 = posSlot;
if (++rep0 == (UInt32)(0))
{
/* it's for stream version */
len = kLzmaStreamWasFinishedId;
break;
}
}
len += kMatchMinLen;
#ifdef _LZMA_OUT_READ
if (rep0 > distanceLimit)
#else
if (rep0 > nowPos)
#endif
return LZMA_RESULT_DATA_ERROR;
#ifdef _LZMA_OUT_READ
if (dictionarySize - distanceLimit > (UInt32)len)
distanceLimit += len;
else
distanceLimit = dictionarySize;
#endif
do
{
#ifdef _LZMA_OUT_READ
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
#else
previousByte = outStream[nowPos - rep0];
#endif
len--;
outStream[nowPos++] = previousByte;
}
while(len != 0 && nowPos < outSize);
}
}
RC_NORMALIZE;
#ifdef _LZMA_OUT_READ
vs->Range = Range;
vs->Code = Code;
vs->DictionaryPos = dictionaryPos;
vs->GlobalPos = globalPos + (UInt32)nowPos;
vs->DistanceLimit = distanceLimit;
vs->Reps[0] = rep0;
vs->Reps[1] = rep1;
vs->Reps[2] = rep2;
vs->Reps[3] = rep3;
vs->State = state;
vs->RemainLen = len;
vs->TempDictionary[0] = tempDictionary[0];
#endif
#ifdef _LZMA_IN_CB
vs->Buffer = Buffer;
vs->BufferLim = BufferLim;
#else
*inSizeProcessed = (SizeT)(Buffer - inStream);
#endif
*outSizeProcessed = nowPos;
return LZMA_RESULT_OK;
}

@ -2,6 +2,7 @@
TARGET=c3600
MACHCODE=0x1e
TEXTADDR=0x80008000
LOADADDR=0x80028000
ifndef CROSS_COMPILE
CROSS_COMPILE=mips-elf-
endif
@ -12,6 +13,7 @@ LDFLAGS=-Ttext ${TEXTADDR}
# TARGET=c3600
# MACHCODE=0x34
# TEXTADDR=0x80008000
# LOADADDR=0x80028000
# ifndef CROSS_COMPILE
# CROSS_COMPILE=mips-elf-
# endif
@ -22,6 +24,7 @@ LDFLAGS=-Ttext ${TEXTADDR}
# TARGET=c1700
# MACHCODE=0x33
# TEXTADDR=0x80008000
# LOADADDR=0x80028000
# ifndef CROSS_COMPILE
# CROSS_COMPILE=powerpc-elf-
# endif
@ -48,14 +51,15 @@ RAW=${OBJCOPY} --strip-unneeded --alt-machine-code ${MACHCODE}
INCLUDE=-Iinclude/ -Imach/${TARGET} -Iinclude/mach/${TARGET}
CFLAGS+=-fno-builtin -fomit-frame-pointer -fno-pic \
-Wall
-Wall -DLOADADDR=${LOADADDR}
ASFLAGS=-D__ASSEMBLY__-xassembler-with-cpp -traditional-cpp
LDFLAGS+=--omagic -nostartfiles -nostdlib --discard-all --strip-all \
--entry _start
OBJECTS=string.o main.o ciloio.o printf.o elf_loader.o
OBJECTS=string.o main.o ciloio.o printf.o elf_loader.o lzma_loader.o \
LzmaDecode.o
LINKOBJ=${OBJECTS} $(MACHDIR)/promlib.o $(MACHDIR)/start.o $(MACHDIR)/platio.o\
$(MACHDIR)/platform.o

@ -1,6 +1,6 @@
/**
* CILO Elf Loader
* (c) 2008 Philippe Vachoon <philippe@cowpig.ca>
* (c) 2008 Philippe Vachon <philippe@cowpig.ca>
*
* Licensed under the GNU General Public License v2. See COPYING
* in the distribution source directory for more information.
@ -13,7 +13,6 @@
/* platform-specific defines */
#include <platform.h>
/**
* load a single ELF section into memory at address. Assumes ELF data is
* contiguous in memory.
@ -31,11 +30,12 @@ void load_elf32_section(struct file *fp, uint32_t address,
printf("Init data: %08x length %08x\n", address, length);
#endif
cilo_seek(fp, file_offset, SEEK_SET);
cilo_read(elf_loc, length, 1, fp);
cilo_seek(fp, (uint32_t)file_offset, SEEK_SET);
cilo_read(elf_loc, (uint32_t)length, 1, fp);
}
/**
* Create an uninitialized data (.bss) region of memory.
* @param address Start address of this region
@ -80,8 +80,7 @@ int load_elf32_file(struct file *fp, char *cmd_line)
return -1;
}
/* check machine class: */
if (!(hdr.ident[ELF_INDEX_CLASS] == ELF_CLASS_32 ||
hdr.ident[ELF_INDEX_CLASS] == ELF_CLASS_64))
if (!hdr.ident[ELF_INDEX_CLASS] == ELF_CLASS_32)
{
printf("Invalid ELF machine class found. Found: %2x.\n",
hdr.ident[ELF_INDEX_CLASS]);
@ -106,7 +105,6 @@ int load_elf32_file(struct file *fp, char *cmd_line)
int i;
struct elf32_phdr phdr;
uint32_t offset = 0xffffffff;
cilo_seek(fp, hdr.phoff, SEEK_SET);
@ -147,3 +145,109 @@ int load_elf32_file(struct file *fp, char *cmd_line)
return -1; /* something failed, badly */
}
/**
* load a single ELF section into memory at address. Assumes ELF data is
* contiguous in memory.
* @param base location (in memory) of the ELF file
* @param address address at which the ELF section will be loaded
* @param file_offset offset (in bytes) in the ELF file where the section is
* @param length Length of the section (in bytes)
*/
void load_elf64_section(struct file *fp, uint64_t address,
uint64_t file_offset, uint64_t length)
{
uint8_t *elf_loc = (uint8_t *)address;
#ifdef DEBUG
printf("Init data: %016x length %016x\n", address, length);
#endif
cilo_seek(fp, (uint32_t)file_offset, SEEK_SET);
cilo_read(elf_loc, (uint32_t)length, 1, fp);
}
/**
* Create an uninitialized data (.bss) region of memory.
* @param address Start address of this region
* @param lenght length of this region
*/
void load_elf64_uninitialized_memory(uint64_t address, uint64_t length)
{
int i = 0;
uint8_t *p = (uint8_t *)address;
#ifdef DEBUG
printf("Uninit data: %016x, len %016x\n", address, length);
#endif
for (i = 0; i < length; i++) {
p[i] = 0;
}
}
int load_elf64_file(struct file *fp, char *cmd_line)
{
struct elf64_hdr hdr;
uint32_t mem_sz = 0;
cilo_seek(fp, 0, SEEK_SET);
/* read in header entries */
cilo_read(&hdr, sizeof(struct elf64_hdr), 1, fp);
/* check the file magic */
if (hdr.e_ident[0] != ELF_MAGIC_1 || hdr.e_ident[1] != ELF_MAGIC_2 ||
hdr.e_ident[2] != ELF_MAGIC_3 || hdr.e_ident[3] != ELF_MAGIC_4)
{
printf("Bad ELF magic found. Found: %#2x %#2x %#2x %#2x.\n",
hdr.e_ident[0], hdr.e_ident[1], hdr.e_ident[2], hdr.e_ident[3]);
return -1;
}
/* check machine class: */
if (!hdr.e_ident[ELF_INDEX_CLASS] == ELF_CLASS_64)
{
printf("Invalid ELF machine class found. Found: %2x.\n",
hdr.e_ident[ELF_INDEX_CLASS]);
return -1;
}
/* check endianess: */
if (hdr.e_ident[ELF_INDEX_DATA] != ELF_DATA_MSB) {
printf("Non-big endian ELF file detected. Aborting load.\n");
return -1;
}
if (hdr.e_ehsize != 52 /* bytes */) {
printf("Warning: ELF header greater than 52 bytes found. Found: %u\n",
hdr.e_ehsize);
}
if (hdr.e_phnum == 0) {
printf("Found zero segments in ELF file. Aborting load.\n");
return -1;
}
cilo_seek(fp, hdr.e_phoff, SEEK_SET);
struct elf64_phdr phdr;
int i;
for (i = 0; i < hdr.e_phnum; i++) {
cilo_read(&phdr, sizeof(struct elf64_phdr), 1, fp);
if (phdr.p_type != ELF_PT_LOAD) continue;
load_elf64_section(fp, phdr.p_paddr, phdr.p_offset, phdr.p_filesz);
mem_sz += phdr.p_memsz;
if (phdr.p_memsz - phdr.p_filesz > 0)
{
load_elf64_uninitialized_memory(phdr.p_paddr + phdr.p_filesz,
phdr.p_memsz - phdr.p_filesz);
}
}
return -1;
}

@ -0,0 +1,113 @@
/*
LzmaDecode.h
LZMA Decoder interface
LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
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
#include "LzmaTypes.h"
#define _LZMA_IN_CB 1
/* 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 */
#ifdef _LZMA_PROB32
#define CProb UInt32
#else
#define CProb UInt16
#endif
#define LZMA_RESULT_OK 0
#define LZMA_RESULT_DATA_ERROR 1
#ifdef _LZMA_IN_CB
typedef struct _ILzmaInCallback
{
int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize);
} ILzmaInCallback;
#endif
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#define LZMA_PROPERTIES_SIZE 5
typedef struct _CLzmaProperties
{
int lc;
int lp;
int pb;
#ifdef _LZMA_OUT_READ
UInt32 DictionarySize;
#endif
}CLzmaProperties;
int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
#define kLzmaNeedInitId (-2)
typedef struct _CLzmaDecoderState
{
CLzmaProperties Properties;
CProb *Probs;
#ifdef _LZMA_IN_CB
const unsigned char *Buffer;
const unsigned char *BufferLim;
#endif
#ifdef _LZMA_OUT_READ
unsigned char *Dictionary;
UInt32 Range;
UInt32 Code;
UInt32 DictionaryPos;
UInt32 GlobalPos;
UInt32 DistanceLimit;
UInt32 Reps[4];
int State;
int RemainLen;
unsigned char TempDictionary[4];
#endif
} CLzmaDecoderState;
#ifdef _LZMA_OUT_READ
#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; }
#endif
int LzmaDecode(CLzmaDecoderState *vs,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback,
#else
const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
#endif
unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
#endif

@ -0,0 +1,45 @@
/*
LzmaTypes.h
Types for LZMA Decoder
This file written and distributed to public domain by Igor Pavlov.
This file is part of LZMA SDK 4.40 (2006-05-01)
*/
#ifndef __LZMATYPES_H
#define __LZMATYPES_H
#ifndef _7ZIP_BYTE_DEFINED
#define _7ZIP_BYTE_DEFINED
typedef unsigned char Byte;
#endif
#ifndef _7ZIP_UINT16_DEFINED
#define _7ZIP_UINT16_DEFINED
typedef unsigned short UInt16;
#endif
#ifndef _7ZIP_UINT32_DEFINED
#define _7ZIP_UINT32_DEFINED
#ifdef _LZMA_UINT32_IS_ULONG
typedef unsigned long UInt32;
#else
typedef unsigned int UInt32;
#endif
#endif
#define _LZMA_NO_SYSTEM_SIZE_T
/* You can use it, if you don't want <stddef.h> */
#ifndef _7ZIP_SIZET_DEFINED
#define _7ZIP_SIZET_DEFINED
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
#include <stddef.h>
typedef size_t SizeT;
#endif
#endif
#endif

@ -18,6 +18,8 @@ struct file {
#define SEEK_CUR 1
#define SEEK_END 2
#define cilo_tell(fp) ((fp)->file_pos)
struct file cilo_open(const char *filename);
int32_t cilo_read(void *pbuf, uint32_t size, uint32_t nmemb,
struct file *fp);

@ -56,6 +56,24 @@ struct elf32_header {
uint16_t shstrndx; /* index of string table entry in the section hdr */
};
/* ELF64 Header */
struct elf64_hdr {
uint8_t e_ident[ELF_IDENT_COUNT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint64_t e_entry;
uint64_t e_phoff;
uint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
};
/* ELF magic */
#define ELF_MAGIC_1 0x7f
#define ELF_MAGIC_2 0x45
@ -105,6 +123,19 @@ struct elf32_section_header {
uint32_t entsize; /* per-entry size */
};
struct elf64_shdr {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
};
/* Section Types */
#define ELF_SHT_NULL 0 /* inactive/no associated section */
#define ELF_SHT_PROGBITS 1 /* program-specific information */
@ -195,6 +226,17 @@ struct elf32_phdr {
uint32_t align; /* alignment requirements for loading */
};
struct elf64_phdr {
uint32_t p_type;
uint32_t p_flags;
uint64_t p_offset;
uint64_t p_vaddr;
uint64_t p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
};
/* Segment Types */
#define ELF_PT_NULL 0 /* unused */
#define ELF_PT_LOAD 1 /* loadable segment */

@ -0,0 +1,9 @@
#ifndef _INCLUDE_LZMA_LOADER_H
#define _INCLUDE_LZMA_LOADER_H
#include <types.h>
#include <ciloio.h>
void load_lzma(struct file *fp, uint32_t load_address, char *cmd_line);
#endif /* _INCLUDE_LZMA_LOADER_H */

@ -0,0 +1,105 @@
/*
* LZMA Compressed Kernel Loader
* (c) 2009 Philippe Vachon <philippe@cowpig.ca>
*
* Licensed under the GNU General Public License v.2.
* See COPYING in the root directory of this source distribution for more
* details.
*/
#include <printf.h>
#include <promlib.h>
#include <lzma_loader.h>
#include <ciloio.h>
/* LZMA SDK */
#include <LzmaDecode.h>
struct private_data {
ILzmaInCallback callback;
uint8_t *buffer;
struct file *fp;
};
int read_data(void *object, const uint8_t **buffer, uint32_t *size)
{
struct private_data *pvt = (struct private_data *)object;
if (cilo_tell(pvt->fp) > pvt->fp->file_len) {
printf("FATAL: Attempt to read past end of file. Aborting.\n");
return LZMA_RESULT_DATA_ERROR;
}
*size = pvt->fp->file_len - cilo_tell(pvt->fp);
*size = *size > 512 ? 512 : *size;
cilo_read(pvt->buffer, *size, 1, pvt->fp);
*buffer = pvt->buffer;
return LZMA_RESULT_OK;
}
void load_lzma(struct file *fp, uint32_t load_address, char *cmd_line)
{
CLzmaDecoderState state;
uint8_t buffer[512];
struct private_data pvt;
uint8_t props[LZMA_PROPERTIES_SIZE];
uint32_t out_size = 0;
uint8_t out_size_read[4];
/* seek to beginning of file */
cilo_seek(fp, 0, SEEK_SET);
/* Setup LZMA decoding properties */
cilo_read(props, LZMA_PROPERTIES_SIZE, 1, fp);
if (LzmaDecodeProperties(&state.Properties, props, LZMA_PROPERTIES_SIZE)
!= LZMA_RESULT_OK)
{
printf("Error while decoding LZMA properties. Aborting.\n");
return;
}
/* read in out size */
cilo_read(out_size_read, 1, 4, fp);
out_size = out_size_read[0] | out_size_read[1] << 8 |
out_size_read[2] << 16 | out_size_read[3] << 24;
cilo_seek(fp, 4, SEEK_CUR);
uint16_t probs[LzmaGetNumProbs(&state.Properties)];
printf("Number of probability table entries: %d\n",
LzmaGetNumProbs(&state.Properties));
printf("Size of uncompressed file: %08x.\n", out_size);
/* setup structs */
pvt.callback.Read = read_data;
pvt.buffer = buffer;
pvt.fp = fp;
state.Probs = probs;
/* do the decoding */
uint32_t out_processed = 0;
printf("Loading kernel at %08x\n", load_address);
int result = LzmaDecode(&state, (ILzmaInCallback *)&pvt,
(uint8_t *)load_address, out_size, &out_processed);
if (result != LZMA_RESULT_OK) {
printf("Error in decoding LZMA-compressed kernel image. Aborting.\n");
return;
}
/* kick into kernel: */
printf("Starting LZMA decompressed kernel at %16x.\n", load_address);
((void (*)(uint32_t mem_sz, char *cmd_line))(load_address))
(c_memsz(), cmd_line);
}

@ -32,6 +32,9 @@ void c_puts(const char *s)
{
while(*s != '\0') {
c_putc(*(s++));
if (*s == '\n') {
c_putc('\r');
}
}
}

@ -6,6 +6,7 @@
#include <addr.h>
#include <elf.h>
#include <elf_loader.h>
#include <lzma_loader.h>
#include <ciloio.h>
#include <promlib.h>
@ -108,11 +109,25 @@ enter_filename:
struct file kernel_file = cilo_open(kernel);
if (kernel_file.code == 0) {
printf("Unable to find \"%s\" on the flash filesystem.\n", kernel);
printf("Unable to find \"%s\" on the specified filesystem.\n",
kernel);
goto enter_filename;
}
/* check if this is an LZMA-compressed kernel image. */
if (strstr(kernel, "lzma")) {
printf("Loading LZMA-compressed kernel image.\n");
load_lzma(&kernel_file, LOADADDR, cmd_line);
} else {
#ifdef DEBUG
printf("DEBUG: cmd_line: %s\n", cmd_line);
#endif
struct elf32_header hdr;
cilo_read(&hdr, sizeof(struct elf32_header), 1, &kernel_file);
cilo_seek(&kernel_file, 0, SEEK_SET);
/* check if this is a 32-bit or 64-bit kernel image. */
printf("Booting %s.\n", kernel);
if (load_elf32_file(&kernel_file, cmd_line)
< 0)
@ -120,7 +135,6 @@ enter_filename:
printf("Fatal error while loading kernel. Aborting.\n");
}
}
goto enter_filename;
/* return to ROMMON */
goto enter_filename;
}

Loading…
Cancel
Save