2005-06-14 10:03:57 +03:00
|
|
|
/* 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>
|
2005-07-25 12:34:53 +03:00
|
|
|
#include "gzip.h"
|
|
|
|
#include "LzmaDecode.h"
|
2005-06-14 10:03:57 +03:00
|
|
|
|
|
|
|
/* Function prototypes */
|
2005-07-25 12:34:53 +03:00
|
|
|
unsigned char get_byte(void);
|
2005-06-14 10:03:57 +03:00
|
|
|
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 */
|
2005-07-25 12:34:53 +03:00
|
|
|
void (*prnt)(unsigned int, char *); /* Gen reference to Yamon print function */
|
|
|
|
void printf(char *ptr); /* Generate our own printf */
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
int tikernelunzip(int argc, char *argv[], char *arge[])
|
2005-06-14 10:03:57 +03:00
|
|
|
{
|
2005-07-25 12:34:53 +03:00
|
|
|
extern unsigned int _ftext;
|
|
|
|
extern uch kernelimage[];
|
|
|
|
uch *in, *out;
|
|
|
|
int status;
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
printf("Launching kernel decompressor.\n");
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
out = (unsigned char *) LOADADDR;
|
|
|
|
in = &(kernelimage[0]);
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
status = tidecompress(in, out);
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
if (status == 0) {
|
|
|
|
printf("Kernel decompressor was successful ... launching kernel.\n");
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
ke = ( void(*)(int, char *[],char*[]))kernel_entry;
|
|
|
|
(*ke)(argc,argv,arge);
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
return (0);
|
|
|
|
} else {
|
|
|
|
printf("Error in decompression.\n");
|
|
|
|
return(1);
|
|
|
|
}
|
2005-06-14 10:03:57 +03:00
|
|
|
}
|
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
#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)
|
2005-06-14 10:03:57 +03:00
|
|
|
{
|
2005-07-25 12:34:53 +03:00
|
|
|
int j;
|
|
|
|
char buf[11];
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
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;
|
|
|
|
}
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
printf(buf);
|
2005-06-14 10:03:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int tidecompress(uch *indata, uch *outdata)
|
|
|
|
{
|
2005-07-25 12:34:53 +03:00
|
|
|
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;
|
2005-06-14 10:03:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void printf(char *ptr)
|
|
|
|
{
|
2005-07-25 12:34:53 +03:00
|
|
|
unsigned int *tempptr = (unsigned int *)0x90000534;
|
|
|
|
prnt = ( void (*)(unsigned int, char *)) *tempptr;
|
|
|
|
(*prnt)(0,ptr);
|
2005-06-14 10:03:57 +03:00
|
|
|
}
|
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
unsigned char get_byte()
|
2005-06-14 10:03:57 +03:00
|
|
|
{
|
2005-07-25 12:34:53 +03:00
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
c = *input_data;
|
|
|
|
input_data++;
|
2005-06-14 10:03:57 +03:00
|
|
|
|
2005-07-25 12:34:53 +03:00
|
|
|
return c;
|
2005-06-14 10:03:57 +03:00
|
|
|
}
|
|
|
|
|