Merge branch 'unlikely/sched' of git://git.kernel.org/pub/scm/linux/kernel/git/rosted...
[pandora-kernel.git] / arch / arm / boot / compressed / misc.c
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 <linux/linkage.h>
27 #include <asm/string.h>
28
29
30 static void putstr(const char *ptr);
31 extern void error(char *x);
32
33 #include <mach/uncompress.h>
34
35 #ifdef CONFIG_DEBUG_ICEDCC
36
37 #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
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
53
54 #elif defined(CONFIG_CPU_XSCALE)
55
56 static void icedcc_putc(int ch)
57 {
58         int status, i = 0x4000000;
59
60         do {
61                 if (--i < 0)
62                         return;
63
64                 asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
65         } while (status & (1 << 28));
66
67         asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
68 }
69
70 #else
71
72 static void icedcc_putc(int ch)
73 {
74         int status, i = 0x4000000;
75
76         do {
77                 if (--i < 0)
78                         return;
79
80                 asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
81         } while (status & 2);
82
83         asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
84 }
85
86 #endif
87
88 #define putc(ch)        icedcc_putc(ch)
89 #endif
90
91 static void putstr(const char *ptr)
92 {
93         char c;
94
95         while ((c = *ptr++) != '\0') {
96                 if (c == '\n')
97                         putc('\r');
98                 putc(c);
99         }
100
101         flush();
102 }
103
104
105 void *memcpy(void *__dest, __const void *__src, size_t __n)
106 {
107         int i = 0;
108         unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
109
110         for (i = __n >> 3; i > 0; i--) {
111                 *d++ = *s++;
112                 *d++ = *s++;
113                 *d++ = *s++;
114                 *d++ = *s++;
115                 *d++ = *s++;
116                 *d++ = *s++;
117                 *d++ = *s++;
118                 *d++ = *s++;
119         }
120
121         if (__n & 1 << 2) {
122                 *d++ = *s++;
123                 *d++ = *s++;
124                 *d++ = *s++;
125                 *d++ = *s++;
126         }
127
128         if (__n & 1 << 1) {
129                 *d++ = *s++;
130                 *d++ = *s++;
131         }
132
133         if (__n & 1)
134                 *d++ = *s++;
135
136         return __dest;
137 }
138
139 /*
140  * gzip declarations
141  */
142 extern char input_data[];
143 extern char input_data_end[];
144
145 unsigned char *output_data;
146
147 unsigned long free_mem_ptr;
148 unsigned long free_mem_end_ptr;
149
150 #ifndef arch_error
151 #define arch_error(x)
152 #endif
153
154 void error(char *x)
155 {
156         arch_error(x);
157
158         putstr("\n\n");
159         putstr(x);
160         putstr("\n\n -- System halted");
161
162         while(1);       /* Halt */
163 }
164
165 asmlinkage void __div0(void)
166 {
167         error("Attempting division by 0!");
168 }
169
170 extern int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
171
172
173 void
174 decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
175                 unsigned long free_mem_ptr_end_p,
176                 int arch_id)
177 {
178         int ret;
179
180         output_data             = (unsigned char *)output_start;
181         free_mem_ptr            = free_mem_ptr_p;
182         free_mem_end_ptr        = free_mem_ptr_end_p;
183         __machine_arch_type     = arch_id;
184
185         arch_decomp_setup();
186
187         putstr("Uncompressing Linux...");
188         ret = do_decompress(input_data, input_data_end - input_data,
189                             output_data, error);
190         if (ret)
191                 error("decompressor returned an error");
192         else
193                 putstr(" done, booting the kernel.\n");
194 }