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