Merge branch 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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 #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 void *memcpy(void *__dest, __const void *__src, size_t __n)
121 {
122         int i = 0;
123         unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
124
125         for (i = __n >> 3; i > 0; i--) {
126                 *d++ = *s++;
127                 *d++ = *s++;
128                 *d++ = *s++;
129                 *d++ = *s++;
130                 *d++ = *s++;
131                 *d++ = *s++;
132                 *d++ = *s++;
133                 *d++ = *s++;
134         }
135
136         if (__n & 1 << 2) {
137                 *d++ = *s++;
138                 *d++ = *s++;
139                 *d++ = *s++;
140                 *d++ = *s++;
141         }
142
143         if (__n & 1 << 1) {
144                 *d++ = *s++;
145                 *d++ = *s++;
146         }
147
148         if (__n & 1)
149                 *d++ = *s++;
150
151         return __dest;
152 }
153
154 /*
155  * gzip delarations
156  */
157 extern char input_data[];
158 extern char input_data_end[];
159
160 unsigned char *output_data;
161 unsigned long output_ptr;
162
163 unsigned long free_mem_ptr;
164 unsigned long free_mem_end_ptr;
165
166 #ifndef arch_error
167 #define arch_error(x)
168 #endif
169
170 void error(char *x)
171 {
172         arch_error(x);
173
174         putstr("\n\n");
175         putstr(x);
176         putstr("\n\n -- System halted");
177
178         while(1);       /* Halt */
179 }
180
181 asmlinkage void __div0(void)
182 {
183         error("Attempting division by 0!");
184 }
185
186 extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
187
188 #ifndef STANDALONE_DEBUG
189
190 unsigned long
191 decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
192                 unsigned long free_mem_ptr_end_p,
193                 int arch_id)
194 {
195         unsigned char *tmp;
196
197         output_data             = (unsigned char *)output_start;
198         free_mem_ptr            = free_mem_ptr_p;
199         free_mem_end_ptr        = free_mem_ptr_end_p;
200         __machine_arch_type     = arch_id;
201
202         arch_decomp_setup();
203
204         tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
205         output_ptr = get_unaligned_le32(tmp);
206
207         putstr("Uncompressing Linux...");
208         do_decompress(input_data, input_data_end - input_data,
209                         output_data, error);
210         putstr(" done, booting the kernel.\n");
211         return output_ptr;
212 }
213 #else
214
215 char output_buffer[1500*1024];
216
217 int main()
218 {
219         output_data = output_buffer;
220
221         putstr("Uncompressing Linux...");
222         decompress(input_data, input_data_end - input_data,
223                         NULL, NULL, output_data, NULL, error);
224         putstr("done.\n");
225         return 0;
226 }
227 #endif