1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * misc.c 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * This is a collection of several routines from gzip-1.0.3 5*1da177e4SLinus Torvalds * adapted for Linux. 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * Modified for ARM Linux by Russell King 10*1da177e4SLinus Torvalds * 11*1da177e4SLinus Torvalds * Nicolas Pitre <nico@visuaide.com> 1999/04/14 : 12*1da177e4SLinus Torvalds * For this code to run directly from Flash, all constant variables must 13*1da177e4SLinus Torvalds * be marked with 'const' and all other variables initialized at run-time 14*1da177e4SLinus Torvalds * only. This way all non constant variables will end up in the bss segment, 15*1da177e4SLinus Torvalds * which should point to addresses in RAM and cleared to 0 on start. 16*1da177e4SLinus Torvalds * This allows for a much quicker boot time. 17*1da177e4SLinus Torvalds */ 18*1da177e4SLinus Torvalds 19*1da177e4SLinus Torvalds unsigned int __machine_arch_type; 20*1da177e4SLinus Torvalds 21*1da177e4SLinus Torvalds #include <linux/string.h> 22*1da177e4SLinus Torvalds 23*1da177e4SLinus Torvalds #include <asm/arch/uncompress.h> 24*1da177e4SLinus Torvalds 25*1da177e4SLinus Torvalds #ifdef STANDALONE_DEBUG 26*1da177e4SLinus Torvalds #define putstr printf 27*1da177e4SLinus Torvalds #endif 28*1da177e4SLinus Torvalds 29*1da177e4SLinus Torvalds #ifdef CONFIG_DEBUG_ICEDCC 30*1da177e4SLinus Torvalds #define putstr icedcc_putstr 31*1da177e4SLinus Torvalds #define putc icedcc_putc 32*1da177e4SLinus Torvalds 33*1da177e4SLinus Torvalds extern void idedcc_putc(int ch); 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds static void 36*1da177e4SLinus Torvalds icedcc_putstr(const char *ptr) 37*1da177e4SLinus Torvalds { 38*1da177e4SLinus Torvalds for (; *ptr != '\0'; ptr++) { 39*1da177e4SLinus Torvalds icedcc_putc(*ptr); 40*1da177e4SLinus Torvalds } 41*1da177e4SLinus Torvalds } 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds #endif 44*1da177e4SLinus Torvalds 45*1da177e4SLinus Torvalds #define __ptr_t void * 46*1da177e4SLinus Torvalds 47*1da177e4SLinus Torvalds /* 48*1da177e4SLinus Torvalds * Optimised C version of memzero for the ARM. 49*1da177e4SLinus Torvalds */ 50*1da177e4SLinus Torvalds void __memzero (__ptr_t s, size_t n) 51*1da177e4SLinus Torvalds { 52*1da177e4SLinus Torvalds union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; 53*1da177e4SLinus Torvalds int i; 54*1da177e4SLinus Torvalds 55*1da177e4SLinus Torvalds u.vp = s; 56*1da177e4SLinus Torvalds 57*1da177e4SLinus Torvalds for (i = n >> 5; i > 0; i--) { 58*1da177e4SLinus Torvalds *u.ulp++ = 0; 59*1da177e4SLinus Torvalds *u.ulp++ = 0; 60*1da177e4SLinus Torvalds *u.ulp++ = 0; 61*1da177e4SLinus Torvalds *u.ulp++ = 0; 62*1da177e4SLinus Torvalds *u.ulp++ = 0; 63*1da177e4SLinus Torvalds *u.ulp++ = 0; 64*1da177e4SLinus Torvalds *u.ulp++ = 0; 65*1da177e4SLinus Torvalds *u.ulp++ = 0; 66*1da177e4SLinus Torvalds } 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds if (n & 1 << 4) { 69*1da177e4SLinus Torvalds *u.ulp++ = 0; 70*1da177e4SLinus Torvalds *u.ulp++ = 0; 71*1da177e4SLinus Torvalds *u.ulp++ = 0; 72*1da177e4SLinus Torvalds *u.ulp++ = 0; 73*1da177e4SLinus Torvalds } 74*1da177e4SLinus Torvalds 75*1da177e4SLinus Torvalds if (n & 1 << 3) { 76*1da177e4SLinus Torvalds *u.ulp++ = 0; 77*1da177e4SLinus Torvalds *u.ulp++ = 0; 78*1da177e4SLinus Torvalds } 79*1da177e4SLinus Torvalds 80*1da177e4SLinus Torvalds if (n & 1 << 2) 81*1da177e4SLinus Torvalds *u.ulp++ = 0; 82*1da177e4SLinus Torvalds 83*1da177e4SLinus Torvalds if (n & 1 << 1) { 84*1da177e4SLinus Torvalds *u.ucp++ = 0; 85*1da177e4SLinus Torvalds *u.ucp++ = 0; 86*1da177e4SLinus Torvalds } 87*1da177e4SLinus Torvalds 88*1da177e4SLinus Torvalds if (n & 1) 89*1da177e4SLinus Torvalds *u.ucp++ = 0; 90*1da177e4SLinus Torvalds } 91*1da177e4SLinus Torvalds 92*1da177e4SLinus Torvalds static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, 93*1da177e4SLinus Torvalds size_t __n) 94*1da177e4SLinus Torvalds { 95*1da177e4SLinus Torvalds int i = 0; 96*1da177e4SLinus Torvalds unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; 97*1da177e4SLinus Torvalds 98*1da177e4SLinus Torvalds for (i = __n >> 3; i > 0; i--) { 99*1da177e4SLinus Torvalds *d++ = *s++; 100*1da177e4SLinus Torvalds *d++ = *s++; 101*1da177e4SLinus Torvalds *d++ = *s++; 102*1da177e4SLinus Torvalds *d++ = *s++; 103*1da177e4SLinus Torvalds *d++ = *s++; 104*1da177e4SLinus Torvalds *d++ = *s++; 105*1da177e4SLinus Torvalds *d++ = *s++; 106*1da177e4SLinus Torvalds *d++ = *s++; 107*1da177e4SLinus Torvalds } 108*1da177e4SLinus Torvalds 109*1da177e4SLinus Torvalds if (__n & 1 << 2) { 110*1da177e4SLinus Torvalds *d++ = *s++; 111*1da177e4SLinus Torvalds *d++ = *s++; 112*1da177e4SLinus Torvalds *d++ = *s++; 113*1da177e4SLinus Torvalds *d++ = *s++; 114*1da177e4SLinus Torvalds } 115*1da177e4SLinus Torvalds 116*1da177e4SLinus Torvalds if (__n & 1 << 1) { 117*1da177e4SLinus Torvalds *d++ = *s++; 118*1da177e4SLinus Torvalds *d++ = *s++; 119*1da177e4SLinus Torvalds } 120*1da177e4SLinus Torvalds 121*1da177e4SLinus Torvalds if (__n & 1) 122*1da177e4SLinus Torvalds *d++ = *s++; 123*1da177e4SLinus Torvalds 124*1da177e4SLinus Torvalds return __dest; 125*1da177e4SLinus Torvalds } 126*1da177e4SLinus Torvalds 127*1da177e4SLinus Torvalds /* 128*1da177e4SLinus Torvalds * gzip delarations 129*1da177e4SLinus Torvalds */ 130*1da177e4SLinus Torvalds #define OF(args) args 131*1da177e4SLinus Torvalds #define STATIC static 132*1da177e4SLinus Torvalds 133*1da177e4SLinus Torvalds typedef unsigned char uch; 134*1da177e4SLinus Torvalds typedef unsigned short ush; 135*1da177e4SLinus Torvalds typedef unsigned long ulg; 136*1da177e4SLinus Torvalds 137*1da177e4SLinus Torvalds #define WSIZE 0x8000 /* Window size must be at least 32k, */ 138*1da177e4SLinus Torvalds /* and a power of two */ 139*1da177e4SLinus Torvalds 140*1da177e4SLinus Torvalds static uch *inbuf; /* input buffer */ 141*1da177e4SLinus Torvalds static uch window[WSIZE]; /* Sliding window buffer */ 142*1da177e4SLinus Torvalds 143*1da177e4SLinus Torvalds static unsigned insize; /* valid bytes in inbuf */ 144*1da177e4SLinus Torvalds static unsigned inptr; /* index of next byte to be processed in inbuf */ 145*1da177e4SLinus Torvalds static unsigned outcnt; /* bytes in output buffer */ 146*1da177e4SLinus Torvalds 147*1da177e4SLinus Torvalds /* gzip flag byte */ 148*1da177e4SLinus Torvalds #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 149*1da177e4SLinus Torvalds #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 150*1da177e4SLinus Torvalds #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 151*1da177e4SLinus Torvalds #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 152*1da177e4SLinus Torvalds #define COMMENT 0x10 /* bit 4 set: file comment present */ 153*1da177e4SLinus Torvalds #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 154*1da177e4SLinus Torvalds #define RESERVED 0xC0 /* bit 6,7: reserved */ 155*1da177e4SLinus Torvalds 156*1da177e4SLinus Torvalds #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) 157*1da177e4SLinus Torvalds 158*1da177e4SLinus Torvalds /* Diagnostic functions */ 159*1da177e4SLinus Torvalds #ifdef DEBUG 160*1da177e4SLinus Torvalds # define Assert(cond,msg) {if(!(cond)) error(msg);} 161*1da177e4SLinus Torvalds # define Trace(x) fprintf x 162*1da177e4SLinus Torvalds # define Tracev(x) {if (verbose) fprintf x ;} 163*1da177e4SLinus Torvalds # define Tracevv(x) {if (verbose>1) fprintf x ;} 164*1da177e4SLinus Torvalds # define Tracec(c,x) {if (verbose && (c)) fprintf x ;} 165*1da177e4SLinus Torvalds # define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} 166*1da177e4SLinus Torvalds #else 167*1da177e4SLinus Torvalds # define Assert(cond,msg) 168*1da177e4SLinus Torvalds # define Trace(x) 169*1da177e4SLinus Torvalds # define Tracev(x) 170*1da177e4SLinus Torvalds # define Tracevv(x) 171*1da177e4SLinus Torvalds # define Tracec(c,x) 172*1da177e4SLinus Torvalds # define Tracecv(c,x) 173*1da177e4SLinus Torvalds #endif 174*1da177e4SLinus Torvalds 175*1da177e4SLinus Torvalds static int fill_inbuf(void); 176*1da177e4SLinus Torvalds static void flush_window(void); 177*1da177e4SLinus Torvalds static void error(char *m); 178*1da177e4SLinus Torvalds static void gzip_mark(void **); 179*1da177e4SLinus Torvalds static void gzip_release(void **); 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds extern char input_data[]; 182*1da177e4SLinus Torvalds extern char input_data_end[]; 183*1da177e4SLinus Torvalds 184*1da177e4SLinus Torvalds static uch *output_data; 185*1da177e4SLinus Torvalds static ulg output_ptr; 186*1da177e4SLinus Torvalds static ulg bytes_out; 187*1da177e4SLinus Torvalds 188*1da177e4SLinus Torvalds static void *malloc(int size); 189*1da177e4SLinus Torvalds static void free(void *where); 190*1da177e4SLinus Torvalds static void error(char *m); 191*1da177e4SLinus Torvalds static void gzip_mark(void **); 192*1da177e4SLinus Torvalds static void gzip_release(void **); 193*1da177e4SLinus Torvalds 194*1da177e4SLinus Torvalds static void putstr(const char *); 195*1da177e4SLinus Torvalds 196*1da177e4SLinus Torvalds extern int end; 197*1da177e4SLinus Torvalds static ulg free_mem_ptr; 198*1da177e4SLinus Torvalds static ulg free_mem_ptr_end; 199*1da177e4SLinus Torvalds 200*1da177e4SLinus Torvalds #define HEAP_SIZE 0x2000 201*1da177e4SLinus Torvalds 202*1da177e4SLinus Torvalds #include "../../../../lib/inflate.c" 203*1da177e4SLinus Torvalds 204*1da177e4SLinus Torvalds #ifndef STANDALONE_DEBUG 205*1da177e4SLinus Torvalds static void *malloc(int size) 206*1da177e4SLinus Torvalds { 207*1da177e4SLinus Torvalds void *p; 208*1da177e4SLinus Torvalds 209*1da177e4SLinus Torvalds if (size <0) error("Malloc error"); 210*1da177e4SLinus Torvalds if (free_mem_ptr <= 0) error("Memory error"); 211*1da177e4SLinus Torvalds 212*1da177e4SLinus Torvalds free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds p = (void *)free_mem_ptr; 215*1da177e4SLinus Torvalds free_mem_ptr += size; 216*1da177e4SLinus Torvalds 217*1da177e4SLinus Torvalds if (free_mem_ptr >= free_mem_ptr_end) 218*1da177e4SLinus Torvalds error("Out of memory"); 219*1da177e4SLinus Torvalds return p; 220*1da177e4SLinus Torvalds } 221*1da177e4SLinus Torvalds 222*1da177e4SLinus Torvalds static void free(void *where) 223*1da177e4SLinus Torvalds { /* gzip_mark & gzip_release do the free */ 224*1da177e4SLinus Torvalds } 225*1da177e4SLinus Torvalds 226*1da177e4SLinus Torvalds static void gzip_mark(void **ptr) 227*1da177e4SLinus Torvalds { 228*1da177e4SLinus Torvalds arch_decomp_wdog(); 229*1da177e4SLinus Torvalds *ptr = (void *) free_mem_ptr; 230*1da177e4SLinus Torvalds } 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds static void gzip_release(void **ptr) 233*1da177e4SLinus Torvalds { 234*1da177e4SLinus Torvalds arch_decomp_wdog(); 235*1da177e4SLinus Torvalds free_mem_ptr = (long) *ptr; 236*1da177e4SLinus Torvalds } 237*1da177e4SLinus Torvalds #else 238*1da177e4SLinus Torvalds static void gzip_mark(void **ptr) 239*1da177e4SLinus Torvalds { 240*1da177e4SLinus Torvalds } 241*1da177e4SLinus Torvalds 242*1da177e4SLinus Torvalds static void gzip_release(void **ptr) 243*1da177e4SLinus Torvalds { 244*1da177e4SLinus Torvalds } 245*1da177e4SLinus Torvalds #endif 246*1da177e4SLinus Torvalds 247*1da177e4SLinus Torvalds /* =========================================================================== 248*1da177e4SLinus Torvalds * Fill the input buffer. This is called only when the buffer is empty 249*1da177e4SLinus Torvalds * and at least one byte is really needed. 250*1da177e4SLinus Torvalds */ 251*1da177e4SLinus Torvalds int fill_inbuf(void) 252*1da177e4SLinus Torvalds { 253*1da177e4SLinus Torvalds if (insize != 0) 254*1da177e4SLinus Torvalds error("ran out of input data"); 255*1da177e4SLinus Torvalds 256*1da177e4SLinus Torvalds inbuf = input_data; 257*1da177e4SLinus Torvalds insize = &input_data_end[0] - &input_data[0]; 258*1da177e4SLinus Torvalds 259*1da177e4SLinus Torvalds inptr = 1; 260*1da177e4SLinus Torvalds return inbuf[0]; 261*1da177e4SLinus Torvalds } 262*1da177e4SLinus Torvalds 263*1da177e4SLinus Torvalds /* =========================================================================== 264*1da177e4SLinus Torvalds * Write the output window window[0..outcnt-1] and update crc and bytes_out. 265*1da177e4SLinus Torvalds * (Used for the decompressed data only.) 266*1da177e4SLinus Torvalds */ 267*1da177e4SLinus Torvalds void flush_window(void) 268*1da177e4SLinus Torvalds { 269*1da177e4SLinus Torvalds ulg c = crc; 270*1da177e4SLinus Torvalds unsigned n; 271*1da177e4SLinus Torvalds uch *in, *out, ch; 272*1da177e4SLinus Torvalds 273*1da177e4SLinus Torvalds in = window; 274*1da177e4SLinus Torvalds out = &output_data[output_ptr]; 275*1da177e4SLinus Torvalds for (n = 0; n < outcnt; n++) { 276*1da177e4SLinus Torvalds ch = *out++ = *in++; 277*1da177e4SLinus Torvalds c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); 278*1da177e4SLinus Torvalds } 279*1da177e4SLinus Torvalds crc = c; 280*1da177e4SLinus Torvalds bytes_out += (ulg)outcnt; 281*1da177e4SLinus Torvalds output_ptr += (ulg)outcnt; 282*1da177e4SLinus Torvalds outcnt = 0; 283*1da177e4SLinus Torvalds putstr("."); 284*1da177e4SLinus Torvalds } 285*1da177e4SLinus Torvalds 286*1da177e4SLinus Torvalds static void error(char *x) 287*1da177e4SLinus Torvalds { 288*1da177e4SLinus Torvalds putstr("\n\n"); 289*1da177e4SLinus Torvalds putstr(x); 290*1da177e4SLinus Torvalds putstr("\n\n -- System halted"); 291*1da177e4SLinus Torvalds 292*1da177e4SLinus Torvalds while(1); /* Halt */ 293*1da177e4SLinus Torvalds } 294*1da177e4SLinus Torvalds 295*1da177e4SLinus Torvalds #ifndef STANDALONE_DEBUG 296*1da177e4SLinus Torvalds 297*1da177e4SLinus Torvalds ulg 298*1da177e4SLinus Torvalds decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, 299*1da177e4SLinus Torvalds int arch_id) 300*1da177e4SLinus Torvalds { 301*1da177e4SLinus Torvalds output_data = (uch *)output_start; /* Points to kernel start */ 302*1da177e4SLinus Torvalds free_mem_ptr = free_mem_ptr_p; 303*1da177e4SLinus Torvalds free_mem_ptr_end = free_mem_ptr_end_p; 304*1da177e4SLinus Torvalds __machine_arch_type = arch_id; 305*1da177e4SLinus Torvalds 306*1da177e4SLinus Torvalds arch_decomp_setup(); 307*1da177e4SLinus Torvalds 308*1da177e4SLinus Torvalds makecrc(); 309*1da177e4SLinus Torvalds putstr("Uncompressing Linux..."); 310*1da177e4SLinus Torvalds gunzip(); 311*1da177e4SLinus Torvalds putstr(" done, booting the kernel.\n"); 312*1da177e4SLinus Torvalds return output_ptr; 313*1da177e4SLinus Torvalds } 314*1da177e4SLinus Torvalds #else 315*1da177e4SLinus Torvalds 316*1da177e4SLinus Torvalds char output_buffer[1500*1024]; 317*1da177e4SLinus Torvalds 318*1da177e4SLinus Torvalds int main() 319*1da177e4SLinus Torvalds { 320*1da177e4SLinus Torvalds output_data = output_buffer; 321*1da177e4SLinus Torvalds 322*1da177e4SLinus Torvalds makecrc(); 323*1da177e4SLinus Torvalds putstr("Uncompressing Linux..."); 324*1da177e4SLinus Torvalds gunzip(); 325*1da177e4SLinus Torvalds putstr("done.\n"); 326*1da177e4SLinus Torvalds return 0; 327*1da177e4SLinus Torvalds } 328*1da177e4SLinus Torvalds #endif 329*1da177e4SLinus Torvalds 330