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