diff options
Diffstat (limited to 'target/linux/ar7-2.4/image/src/loader.c')
-rw-r--r-- | target/linux/ar7-2.4/image/src/loader.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/target/linux/ar7-2.4/image/src/loader.c b/target/linux/ar7-2.4/image/src/loader.c new file mode 100644 index 0000000..22b909d --- /dev/null +++ b/target/linux/ar7-2.4/image/src/loader.c @@ -0,0 +1,140 @@ +/* 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 <nico@visuaide.com>, 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 <linux/config.h> +#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; +} + |