at v2.6.30 352 lines 6.9 kB view raw
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/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 30static 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 39static 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 54static 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 70static 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 90static 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 */ 112void __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 154static 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 195typedef unsigned char uch; 196typedef unsigned short ush; 197typedef unsigned long ulg; 198 199#define WSIZE 0x8000 /* Window size must be at least 32k, */ 200 /* and a power of two */ 201 202static uch *inbuf; /* input buffer */ 203static uch window[WSIZE]; /* Sliding window buffer */ 204 205static unsigned insize; /* valid bytes in inbuf */ 206static unsigned inptr; /* index of next byte to be processed in inbuf */ 207static 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 237static int fill_inbuf(void); 238static void flush_window(void); 239static void error(char *m); 240 241extern char input_data[]; 242extern char input_data_end[]; 243 244static uch *output_data; 245static ulg output_ptr; 246static ulg bytes_out; 247 248static void error(char *m); 249 250static void putstr(const char *); 251 252extern int end; 253static ulg free_mem_ptr; 254static 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 */ 268int 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 */ 284void 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 307static 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 320ulg 321decompress_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 339char output_buffer[1500*1024]; 340 341int 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