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 19 unsigned int __machine_arch_type; 20 21 #include <linux/compiler.h> /* for inline */ 22 #include <linux/types.h> /* for size_t */ 23 #include <linux/stddef.h> /* for NULL */ 24 #include <asm/string.h> 25 26 #ifdef STANDALONE_DEBUG 27 #define putstr printf 28 #else 29 30 static void putstr(const char *ptr); 31 32 #include <mach/uncompress.h> 33 34 #ifdef CONFIG_DEBUG_ICEDCC 35 36 #ifdef CONFIG_CPU_V6 37 38 static void icedcc_putc(int ch) 39 { 40 int status, i = 0x4000000; 41 42 do { 43 if (--i < 0) 44 return; 45 46 asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status)); 47 } while (status & (1 << 29)); 48 49 asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch)); 50 } 51 #elif defined(CONFIG_CPU_XSCALE) 52 53 static void icedcc_putc(int ch) 54 { 55 int status, i = 0x4000000; 56 57 do { 58 if (--i < 0) 59 return; 60 61 asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status)); 62 } while (status & (1 << 28)); 63 64 asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch)); 65 } 66 67 #else 68 69 static void icedcc_putc(int ch) 70 { 71 int status, i = 0x4000000; 72 73 do { 74 if (--i < 0) 75 return; 76 77 asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status)); 78 } while (status & 2); 79 80 asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch)); 81 } 82 83 #endif 84 85 #define putc(ch) icedcc_putc(ch) 86 #define flush() do { } while (0) 87 #endif 88 89 static void putstr(const char *ptr) 90 { 91 char c; 92 93 while ((c = *ptr++) != '\0') { 94 if (c == '\n') 95 putc('\r'); 96 putc(c); 97 } 98 99 flush(); 100 } 101 102 #endif 103 104 #define __ptr_t void * 105 106 #define memzero(s,n) __memzero(s,n) 107 108 /* 109 * Optimised C version of memzero for the ARM. 110 */ 111 void __memzero (__ptr_t s, size_t n) 112 { 113 union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; 114 int i; 115 116 u.vp = s; 117 118 for (i = n >> 5; i > 0; i--) { 119 *u.ulp++ = 0; 120 *u.ulp++ = 0; 121 *u.ulp++ = 0; 122 *u.ulp++ = 0; 123 *u.ulp++ = 0; 124 *u.ulp++ = 0; 125 *u.ulp++ = 0; 126 *u.ulp++ = 0; 127 } 128 129 if (n & 1 << 4) { 130 *u.ulp++ = 0; 131 *u.ulp++ = 0; 132 *u.ulp++ = 0; 133 *u.ulp++ = 0; 134 } 135 136 if (n & 1 << 3) { 137 *u.ulp++ = 0; 138 *u.ulp++ = 0; 139 } 140 141 if (n & 1 << 2) 142 *u.ulp++ = 0; 143 144 if (n & 1 << 1) { 145 *u.ucp++ = 0; 146 *u.ucp++ = 0; 147 } 148 149 if (n & 1) 150 *u.ucp++ = 0; 151 } 152 153 static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, 154 size_t __n) 155 { 156 int i = 0; 157 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; 158 159 for (i = __n >> 3; i > 0; i--) { 160 *d++ = *s++; 161 *d++ = *s++; 162 *d++ = *s++; 163 *d++ = *s++; 164 *d++ = *s++; 165 *d++ = *s++; 166 *d++ = *s++; 167 *d++ = *s++; 168 } 169 170 if (__n & 1 << 2) { 171 *d++ = *s++; 172 *d++ = *s++; 173 *d++ = *s++; 174 *d++ = *s++; 175 } 176 177 if (__n & 1 << 1) { 178 *d++ = *s++; 179 *d++ = *s++; 180 } 181 182 if (__n & 1) 183 *d++ = *s++; 184 185 return __dest; 186 } 187 188 /* 189 * gzip delarations 190 */ 191 #define OF(args) args 192 #define STATIC static 193 194 typedef unsigned char uch; 195 typedef unsigned short ush; 196 typedef unsigned long ulg; 197 198 #define WSIZE 0x8000 /* Window size must be at least 32k, */ 199 /* and a power of two */ 200 201 static uch *inbuf; /* input buffer */ 202 static uch window[WSIZE]; /* Sliding window buffer */ 203 204 static unsigned insize; /* valid bytes in inbuf */ 205 static unsigned inptr; /* index of next byte to be processed in inbuf */ 206 static unsigned outcnt; /* bytes in output buffer */ 207 208 /* gzip flag byte */ 209 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 210 #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ 211 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 212 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 213 #define COMMENT 0x10 /* bit 4 set: file comment present */ 214 #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ 215 #define RESERVED 0xC0 /* bit 6,7: reserved */ 216 217 #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) 218 219 /* Diagnostic functions */ 220 #ifdef DEBUG 221 # define Assert(cond,msg) {if(!(cond)) error(msg);} 222 # define Trace(x) fprintf x 223 # define Tracev(x) {if (verbose) fprintf x ;} 224 # define Tracevv(x) {if (verbose>1) fprintf x ;} 225 # define Tracec(c,x) {if (verbose && (c)) fprintf x ;} 226 # define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} 227 #else 228 # define Assert(cond,msg) 229 # define Trace(x) 230 # define Tracev(x) 231 # define Tracevv(x) 232 # define Tracec(c,x) 233 # define Tracecv(c,x) 234 #endif 235 236 static int fill_inbuf(void); 237 static void flush_window(void); 238 static void error(char *m); 239 240 extern char input_data[]; 241 extern char input_data_end[]; 242 243 static uch *output_data; 244 static ulg output_ptr; 245 static ulg bytes_out; 246 247 static void error(char *m); 248 249 static void putstr(const char *); 250 251 extern int end; 252 static ulg free_mem_ptr; 253 static ulg free_mem_end_ptr; 254 255 #ifdef STANDALONE_DEBUG 256 #define NO_INFLATE_MALLOC 257 #endif 258 259 #define ARCH_HAS_DECOMP_WDOG 260 261 #include "../../../../lib/inflate.c" 262 263 /* =========================================================================== 264 * Fill the input buffer. This is called only when the buffer is empty 265 * and at least one byte is really needed. 266 */ 267 int fill_inbuf(void) 268 { 269 if (insize != 0) 270 error("ran out of input data"); 271 272 inbuf = input_data; 273 insize = &input_data_end[0] - &input_data[0]; 274 275 inptr = 1; 276 return inbuf[0]; 277 } 278 279 /* =========================================================================== 280 * Write the output window window[0..outcnt-1] and update crc and bytes_out. 281 * (Used for the decompressed data only.) 282 */ 283 void flush_window(void) 284 { 285 ulg c = crc; 286 unsigned n; 287 uch *in, *out, ch; 288 289 in = window; 290 out = &output_data[output_ptr]; 291 for (n = 0; n < outcnt; n++) { 292 ch = *out++ = *in++; 293 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); 294 } 295 crc = c; 296 bytes_out += (ulg)outcnt; 297 output_ptr += (ulg)outcnt; 298 outcnt = 0; 299 putstr("."); 300 } 301 302 #ifndef arch_error 303 #define arch_error(x) 304 #endif 305 306 static void error(char *x) 307 { 308 arch_error(x); 309 310 putstr("\n\n"); 311 putstr(x); 312 putstr("\n\n -- System halted"); 313 314 while(1); /* Halt */ 315 } 316 317 #ifndef STANDALONE_DEBUG 318 319 ulg 320 decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, 321 int arch_id) 322 { 323 output_data = (uch *)output_start; /* Points to kernel start */ 324 free_mem_ptr = free_mem_ptr_p; 325 free_mem_end_ptr = free_mem_ptr_end_p; 326 __machine_arch_type = arch_id; 327 328 arch_decomp_setup(); 329 330 makecrc(); 331 putstr("Uncompressing Linux..."); 332 gunzip(); 333 putstr(" done, booting the kernel.\n"); 334 return output_ptr; 335 } 336 #else 337 338 char output_buffer[1500*1024]; 339 340 int main() 341 { 342 output_data = output_buffer; 343 344 makecrc(); 345 putstr("Uncompressing Linux..."); 346 gunzip(); 347 putstr("done.\n"); 348 return 0; 349 } 350 #endif 351 352