/* inflate.c -- Not copyrighted 1992 by Mark Adler version c10p1, 10 January 1993 */ /* * Adapted for booting Linux by Hannu Savolainen 1993 * based on gzip-1.0.3 * * Nicolas Pitre , 1999/04/14 : * Little mods for all variable to reside either into rodata or bss segments * by marking constant variables with 'const' and initializing all the others * at run-time only. This allows for the kernel uncompressor to run * directly from Flash or ROM memory on embeded systems. */ #include #include "gzip.h" #include "LzmaDecode.h" /* Function prototypes */ unsigned char get_byte(void); int tikernelunzip(int,char *[], char *[]); static int tidecompress(uch *, uch *); void kernel_entry(int, char *[], char *[]); void (*ke)(int, char *[], char *[]); /* Gen reference to kernel function */ void (*prnt)(unsigned int, char *); /* Gen reference to Yamon print function */ void printf(char *ptr); /* Generate our own printf */ int tikernelunzip(int argc, char *argv[], char *arge[]) { extern unsigned int _ftext; extern uch kernelimage[]; uch *in, *out; int status; printf("Launching kernel decompressor.\n"); out = (unsigned char *) LOADADDR; in = &(kernelimage[0]); status = tidecompress(in, out); if (status == 0) { printf("Kernel decompressor was successful ... launching kernel.\n"); ke = ( void(*)(int, char *[],char*[]))kernel_entry; (*ke)(argc,argv,arge); return (0); } else { printf("Error in decompression.\n"); return(1); } } #if 0 char hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; void print_i(int i) { int j; char buf[11]; buf[0] = '0'; buf[1] = 'x'; buf[10] = 0; for (j = 0; j < 8; j++) { buf[2 + 7 - j] = hex[i & 0xf]; i = i >> 4; } printf(buf); } #endif int tidecompress(uch *indata, uch *outdata) { extern unsigned int workspace; extern unsigned char kernelimage[], kernelimage_end[]; 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 */ unsigned int wsize; /* window size */ unsigned int insize = kernelimage_end - kernelimage; int status; output_ptr = 0; output_data = outdata; input_data = indata; /* 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(); i = 0; wsize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp))) * sizeof(CProb); if ((status = LzmaDecode((unsigned char *) &workspace, wsize, lc, lp, pb, indata + 13, insize - 13, (unsigned char *) output_data, osize, &i)) == LZMA_RESULT_OK) return 0; return status; } void printf(char *ptr) { unsigned int *tempptr = (unsigned int *)0x90000534; prnt = ( void (*)(unsigned int, char *)) *tempptr; (*prnt)(0,ptr); } unsigned char get_byte() { unsigned char c; c = *input_data; input_data++; return c; }