finally move buildroot-ng to trunk
[openwrt/svn-archive/archive.git] / target / image / ar7 / src / loader.c
diff --git a/target/image/ar7/src/loader.c b/target/image/ar7/src/loader.c
new file mode 100644 (file)
index 0000000..22b909d
--- /dev/null
@@ -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;
+}
+