/* * misc.c * * This is a collection of several routines from gzip-1.0.3 * adapted for Linux. * * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 * * Modified for ARM Linux by Russell King * * Nicolas Pitre 1999/04/14 : * For this code to run directly from Flash, all constant variables must * be marked with 'const' and all other variables initialized at run-time * only. This way all non constant variables will end up in the bss segment, * which should point to addresses in RAM and cleared to 0 on start. * This allows for a much quicker boot time. */ unsigned int __machine_arch_type; #define _LINUX_STRING_H_ #include /* for inline */ #include /* for size_t */ #include /* for NULL */ #include #include static void putstr(const char *ptr); extern void error(char *x); #include #ifdef CONFIG_DEBUG_ICEDCC #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) static void icedcc_putc(int ch) { int status, i = 0x4000000; do { if (--i < 0) return; asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status)); } while (status & (1 << 29)); asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch)); } #elif defined(CONFIG_CPU_V7) static void icedcc_putc(int ch) { asm( "wait: mrc p14, 0, pc, c0, c1, 0 \n\ bcs wait \n\ mcr p14, 0, %0, c0, c5, 0 " : : "r" (ch)); } #elif defined(CONFIG_CPU_XSCALE) static void icedcc_putc(int ch) { int status, i = 0x4000000; do { if (--i < 0) return; asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status)); } while (status & (1 << 28)); asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch)); } #else static void icedcc_putc(int ch) { int status, i = 0x4000000; do { if (--i < 0) return; asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status)); } while (status & 2); asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch)); } #endif #define putc(ch) icedcc_putc(ch) #endif static void putstr(const char *ptr) { char c; while ((c = *ptr++) != '\0') { if (c == '\n') putc('\r'); putc(c); } flush(); } void *memcpy(void *__dest, __const void *__src, size_t __n) { int i = 0; unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; for (i = __n >> 3; i > 0; i--) { *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; } if (__n & 1 << 2) { *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; } if (__n & 1 << 1) { *d++ = *s++; *d++ = *s++; } if (__n & 1) *d++ = *s++; return __dest; } /* * gzip declarations */ extern char input_data[]; extern char input_data_end[]; unsigned char *output_data; unsigned long free_mem_ptr; unsigned long free_mem_end_ptr; #ifndef arch_error #define arch_error(x) #endif void error(char *x) { arch_error(x); putstr("\n\n"); putstr(x); putstr("\n\n -- System halted"); while(1); /* Halt */ } asmlinkage void __div0(void) { error("Attempting division by 0!"); } extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)); void decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, int arch_id) { int ret; output_data = (unsigned char *)output_start; free_mem_ptr = free_mem_ptr_p; free_mem_end_ptr = free_mem_ptr_end_p; __machine_arch_type = arch_id; arch_decomp_setup(); putstr("Uncompressing Linux..."); ret = do_decompress(input_data, input_data_end - input_data, output_data, error); if (ret) error("decompressor returned an error"); else putstr(" done, booting the kernel.\n"); }