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 #define _LINUX_STRING_H_ 22 23 #include <linux/compiler.h> /* for inline */ 24 #include <linux/types.h> /* for size_t */ 25 #include <linux/stddef.h> /* for NULL */ 26 #include <asm/string.h> 27 #include <linux/linkage.h> 28 29 #include <asm/unaligned.h> 30 31 #ifdef STANDALONE_DEBUG 32 #define putstr printf 33 #else 34 35 static void putstr(const char *ptr); 36 37 #include <mach/uncompress.h> 38 39 #ifdef CONFIG_DEBUG_ICEDCC 40 41 #ifdef CONFIG_CPU_V6 42 43 static void icedcc_putc(int ch) 44 { 45 int status, i = 0x4000000; 46 47 do { 48 if (--i < 0) 49 return; 50 51 asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status)); 52 } while (status & (1 << 29)); 53 54 asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch)); 55 } 56 57 #elif defined(CONFIG_CPU_V7) 58 59 static void icedcc_putc(int ch) 60 { 61 asm( 62 "wait: mrc p14, 0, pc, c0, c1, 0 \n\ 63 bcs wait \n\ 64 mcr p14, 0, %0, c0, c5, 0 " 65 : : "r" (ch)); 66 } 67 68 #elif defined(CONFIG_CPU_XSCALE) 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, c14, c0, 0" : "=r" (status)); 79 } while (status & (1 << 28)); 80 81 asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch)); 82 } 83 84 #else 85 86 static void icedcc_putc(int ch) 87 { 88 int status, i = 0x4000000; 89 90 do { 91 if (--i < 0) 92 return; 93 94 asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status)); 95 } while (status & 2); 96 97 asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch)); 98 } 99 100 #endif 101 102 #define putc(ch) icedcc_putc(ch) 103 #endif 104 105 static void putstr(const char *ptr) 106 { 107 char c; 108 109 while ((c = *ptr++) != '\0') { 110 if (c == '\n') 111 putc('\r'); 112 putc(c); 113 } 114 115 flush(); 116 } 117 118 #endif 119 120 #define __ptr_t void * 121 122 #define memzero(s,n) __memzero(s,n) 123 124 /* 125 * Optimised C version of memzero for the ARM. 126 */ 127 void __memzero (__ptr_t s, size_t n) 128 { 129 union { void *vp; unsigned long *ulp; unsigned char *ucp; } u; 130 int i; 131 132 u.vp = s; 133 134 for (i = n >> 5; i > 0; i--) { 135 *u.ulp++ = 0; 136 *u.ulp++ = 0; 137 *u.ulp++ = 0; 138 *u.ulp++ = 0; 139 *u.ulp++ = 0; 140 *u.ulp++ = 0; 141 *u.ulp++ = 0; 142 *u.ulp++ = 0; 143 } 144 145 if (n & 1 << 4) { 146 *u.ulp++ = 0; 147 *u.ulp++ = 0; 148 *u.ulp++ = 0; 149 *u.ulp++ = 0; 150 } 151 152 if (n & 1 << 3) { 153 *u.ulp++ = 0; 154 *u.ulp++ = 0; 155 } 156 157 if (n & 1 << 2) 158 *u.ulp++ = 0; 159 160 if (n & 1 << 1) { 161 *u.ucp++ = 0; 162 *u.ucp++ = 0; 163 } 164 165 if (n & 1) 166 *u.ucp++ = 0; 167 } 168 169 static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, 170 size_t __n) 171 { 172 int i = 0; 173 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; 174 175 for (i = __n >> 3; i > 0; i--) { 176 *d++ = *s++; 177 *d++ = *s++; 178 *d++ = *s++; 179 *d++ = *s++; 180 *d++ = *s++; 181 *d++ = *s++; 182 *d++ = *s++; 183 *d++ = *s++; 184 } 185 186 if (__n & 1 << 2) { 187 *d++ = *s++; 188 *d++ = *s++; 189 *d++ = *s++; 190 *d++ = *s++; 191 } 192 193 if (__n & 1 << 1) { 194 *d++ = *s++; 195 *d++ = *s++; 196 } 197 198 if (__n & 1) 199 *d++ = *s++; 200 201 return __dest; 202 } 203 204 /* 205 * gzip delarations 206 */ 207 #define STATIC static 208 209 /* Diagnostic functions */ 210 #ifdef DEBUG 211 # define Assert(cond,msg) {if(!(cond)) error(msg);} 212 # define Trace(x) fprintf x 213 # define Tracev(x) {if (verbose) fprintf x ;} 214 # define Tracevv(x) {if (verbose>1) fprintf x ;} 215 # define Tracec(c,x) {if (verbose && (c)) fprintf x ;} 216 # define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} 217 #else 218 # define Assert(cond,msg) 219 # define Trace(x) 220 # define Tracev(x) 221 # define Tracevv(x) 222 # define Tracec(c,x) 223 # define Tracecv(c,x) 224 #endif 225 226 static void error(char *m); 227 228 extern char input_data[]; 229 extern char input_data_end[]; 230 231 static unsigned char *output_data; 232 static unsigned long output_ptr; 233 234 static void error(char *m); 235 236 static void putstr(const char *); 237 238 static unsigned long free_mem_ptr; 239 static unsigned long free_mem_end_ptr; 240 241 #ifdef STANDALONE_DEBUG 242 #define NO_INFLATE_MALLOC 243 #endif 244 245 #define ARCH_HAS_DECOMP_WDOG 246 247 #ifdef CONFIG_KERNEL_GZIP 248 #include "../../../../lib/decompress_inflate.c" 249 #endif 250 251 #ifdef CONFIG_KERNEL_LZO 252 #include "../../../../lib/decompress_unlzo.c" 253 #endif 254 255 #ifndef arch_error 256 #define arch_error(x) 257 #endif 258 259 static void error(char *x) 260 { 261 arch_error(x); 262 263 putstr("\n\n"); 264 putstr(x); 265 putstr("\n\n -- System halted"); 266 267 while(1); /* Halt */ 268 } 269 270 asmlinkage void __div0(void) 271 { 272 error("Attempting division by 0!"); 273 } 274 275 #ifndef STANDALONE_DEBUG 276 277 unsigned long 278 decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, 279 unsigned long free_mem_ptr_end_p, 280 int arch_id) 281 { 282 unsigned char *tmp; 283 284 output_data = (unsigned char *)output_start; 285 free_mem_ptr = free_mem_ptr_p; 286 free_mem_end_ptr = free_mem_ptr_end_p; 287 __machine_arch_type = arch_id; 288 289 arch_decomp_setup(); 290 291 tmp = (unsigned char *) (((unsigned long)input_data_end) - 4); 292 output_ptr = get_unaligned_le32(tmp); 293 294 putstr("Uncompressing Linux..."); 295 decompress(input_data, input_data_end - input_data, 296 NULL, NULL, output_data, NULL, error); 297 putstr(" done, booting the kernel.\n"); 298 return output_ptr; 299 } 300 #else 301 302 char output_buffer[1500*1024]; 303 304 int main() 305 { 306 output_data = output_buffer; 307 308 putstr("Uncompressing Linux..."); 309 decompress(input_data, input_data_end - input_data, 310 NULL, NULL, output_data, NULL, error); 311 putstr("done.\n"); 312 return 0; 313 } 314 #endif 315