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 #include <linux/string.h>
22
23 #ifdef STANDALONE_DEBUG
24 #define putstr printf
25 #else
26
27 static void putstr(const char *ptr);
28
29 #include <linux/compiler.h>
30 #include <mach/uncompress.h>
31
32 #ifdef CONFIG_DEBUG_ICEDCC
33
34 #ifdef CONFIG_CPU_V6
35
icedcc_putc(int ch)36 static void icedcc_putc(int ch)
37 {
38 int status, i = 0x4000000;
39
40 do {
41 if (--i < 0)
42 return;
43
44 asm volatile ("mrc p14, 0, %0, c0, c1, 0" : "=r" (status));
45 } while (status & (1 << 29));
46
47 asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
48 }
49
50 #else
51
icedcc_putc(int ch)52 static void icedcc_putc(int ch)
53 {
54 int status, i = 0x4000000;
55
56 do {
57 if (--i < 0)
58 return;
59
60 asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
61 } while (status & 2);
62
63 asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
64 }
65
66 #endif
67
68 #define putc(ch) icedcc_putc(ch)
69 #define flush() do { } while (0)
70 #endif
71
putstr(const char * ptr)72 static void putstr(const char *ptr)
73 {
74 char c;
75
76 while ((c = *ptr++) != '\0') {
77 if (c == '\n')
78 putc('\r');
79 putc(c);
80 }
81
82 flush();
83 }
84
85 #endif
86
87 #define __ptr_t void *
88
89 #define memzero(s,n) __memzero(s,n)
90
91 /*
92 * Optimised C version of memzero for the ARM.
93 */
__memzero(__ptr_t s,size_t n)94 void __memzero (__ptr_t s, size_t n)
95 {
96 union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
97 int i;
98
99 u.vp = s;
100
101 for (i = n >> 5; i > 0; i--) {
102 *u.ulp++ = 0;
103 *u.ulp++ = 0;
104 *u.ulp++ = 0;
105 *u.ulp++ = 0;
106 *u.ulp++ = 0;
107 *u.ulp++ = 0;
108 *u.ulp++ = 0;
109 *u.ulp++ = 0;
110 }
111
112 if (n & 1 << 4) {
113 *u.ulp++ = 0;
114 *u.ulp++ = 0;
115 *u.ulp++ = 0;
116 *u.ulp++ = 0;
117 }
118
119 if (n & 1 << 3) {
120 *u.ulp++ = 0;
121 *u.ulp++ = 0;
122 }
123
124 if (n & 1 << 2)
125 *u.ulp++ = 0;
126
127 if (n & 1 << 1) {
128 *u.ucp++ = 0;
129 *u.ucp++ = 0;
130 }
131
132 if (n & 1)
133 *u.ucp++ = 0;
134 }
135
memcpy(__ptr_t __dest,__const __ptr_t __src,size_t __n)136 static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
137 size_t __n)
138 {
139 int i = 0;
140 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
141
142 for (i = __n >> 3; i > 0; i--) {
143 *d++ = *s++;
144 *d++ = *s++;
145 *d++ = *s++;
146 *d++ = *s++;
147 *d++ = *s++;
148 *d++ = *s++;
149 *d++ = *s++;
150 *d++ = *s++;
151 }
152
153 if (__n & 1 << 2) {
154 *d++ = *s++;
155 *d++ = *s++;
156 *d++ = *s++;
157 *d++ = *s++;
158 }
159
160 if (__n & 1 << 1) {
161 *d++ = *s++;
162 *d++ = *s++;
163 }
164
165 if (__n & 1)
166 *d++ = *s++;
167
168 return __dest;
169 }
170
171 /*
172 * gzip delarations
173 */
174 #define OF(args) args
175 #define STATIC static
176
177 typedef unsigned char uch;
178 typedef unsigned short ush;
179 typedef unsigned long ulg;
180
181 #define WSIZE 0x8000 /* Window size must be at least 32k, */
182 /* and a power of two */
183
184 static uch *inbuf; /* input buffer */
185 static uch window[WSIZE]; /* Sliding window buffer */
186
187 static unsigned insize; /* valid bytes in inbuf */
188 static unsigned inptr; /* index of next byte to be processed in inbuf */
189 static unsigned outcnt; /* bytes in output buffer */
190
191 /* gzip flag byte */
192 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
193 #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
194 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
195 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
196 #define COMMENT 0x10 /* bit 4 set: file comment present */
197 #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
198 #define RESERVED 0xC0 /* bit 6,7: reserved */
199
200 #define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
201
202 /* Diagnostic functions */
203 #ifdef DEBUG
204 # define Assert(cond,msg) {if(!(cond)) error(msg);}
205 # define Trace(x) fprintf x
206 # define Tracev(x) {if (verbose) fprintf x ;}
207 # define Tracevv(x) {if (verbose>1) fprintf x ;}
208 # define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
209 # define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
210 #else
211 # define Assert(cond,msg)
212 # define Trace(x)
213 # define Tracev(x)
214 # define Tracevv(x)
215 # define Tracec(c,x)
216 # define Tracecv(c,x)
217 #endif
218
219 static int fill_inbuf(void);
220 static void flush_window(void);
221 static void error(char *m);
222
223 extern char input_data[];
224 extern char input_data_end[];
225
226 static uch *output_data;
227 static ulg output_ptr;
228 static ulg bytes_out;
229
230 static void error(char *m);
231
232 static void putstr(const char *);
233
234 extern int end;
235 static ulg free_mem_ptr;
236 static ulg free_mem_end_ptr;
237
238 #ifdef STANDALONE_DEBUG
239 #define NO_INFLATE_MALLOC
240 #endif
241
242 #define ARCH_HAS_DECOMP_WDOG
243
244 #include "../../../../lib/inflate.c"
245
246 /* ===========================================================================
247 * Fill the input buffer. This is called only when the buffer is empty
248 * and at least one byte is really needed.
249 */
fill_inbuf(void)250 int fill_inbuf(void)
251 {
252 if (insize != 0)
253 error("ran out of input data");
254
255 inbuf = input_data;
256 insize = &input_data_end[0] - &input_data[0];
257
258 inptr = 1;
259 return inbuf[0];
260 }
261
262 /* ===========================================================================
263 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
264 * (Used for the decompressed data only.)
265 */
flush_window(void)266 void flush_window(void)
267 {
268 ulg c = crc;
269 unsigned n;
270 uch *in, *out, ch;
271
272 in = window;
273 out = &output_data[output_ptr];
274 for (n = 0; n < outcnt; n++) {
275 ch = *out++ = *in++;
276 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
277 }
278 crc = c;
279 bytes_out += (ulg)outcnt;
280 output_ptr += (ulg)outcnt;
281 outcnt = 0;
282 putstr(".");
283 }
284
285 #ifndef arch_error
286 #define arch_error(x)
287 #endif
288
error(char * x)289 static void error(char *x)
290 {
291 arch_error(x);
292
293 putstr("\n\n");
294 putstr(x);
295 putstr("\n\n -- System halted");
296
297 while(1); /* Halt */
298 }
299
300 #ifndef STANDALONE_DEBUG
301
302 ulg
decompress_kernel(ulg output_start,ulg free_mem_ptr_p,ulg free_mem_ptr_end_p,int arch_id)303 decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
304 int arch_id)
305 {
306 output_data = (uch *)output_start; /* Points to kernel start */
307 free_mem_ptr = free_mem_ptr_p;
308 free_mem_end_ptr = free_mem_ptr_end_p;
309 __machine_arch_type = arch_id;
310
311 arch_decomp_setup();
312
313 makecrc();
314 putstr("Uncompressing Linux...");
315 gunzip();
316 putstr(" done, booting the kernel.\n");
317 return output_ptr;
318 }
319 #else
320
321 char output_buffer[1500*1024];
322
main()323 int main()
324 {
325 output_data = output_buffer;
326
327 makecrc();
328 putstr("Uncompressing Linux...");
329 gunzip();
330 putstr("done.\n");
331 return 0;
332 }
333 #endif
334
335