blob: 393c8164131484b03c7f0fa4561d294eb8bd0c31 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
19unsigned int __machine_arch_type;
20
21#include <linux/string.h>
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#ifdef STANDALONE_DEBUG
24#define putstr printf
Russell Kinga0815682006-03-28 10:24:33 +010025#else
26
27static void putstr(const char *ptr);
28
29#include <linux/compiler.h>
Russell Kinga09e64f2008-08-05 16:14:15 +010030#include <mach/uncompress.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
32#ifdef CONFIG_DEBUG_ICEDCC
Tony Lindgren7d95ded2006-09-20 13:03:34 +010033
34#ifdef CONFIG_CPU_V6
35
36static 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}
Jean-Christop PLAGNIOL-VILLARDc633c3c2009-02-25 04:20:40 +010049#elif defined(CONFIG_CPU_XSCALE)
50
51static void icedcc_putc(int ch)
52{
53 int status, i = 0x4000000;
54
55 do {
56 if (--i < 0)
57 return;
58
59 asm volatile ("mrc p14, 0, %0, c14, c0, 0" : "=r" (status));
60 } while (status & (1 << 28));
61
62 asm("mcr p14, 0, %0, c8, c0, 0" : : "r" (ch));
63}
Tony Lindgren7d95ded2006-09-20 13:03:34 +010064
65#else
66
Russell Kingde4533a2006-03-28 10:34:05 +010067static void icedcc_putc(int ch)
68{
69 int status, i = 0x4000000;
70
71 do {
72 if (--i < 0)
73 return;
74
Uwe Zeisbergerb2556da2006-05-02 20:40:56 +010075 asm volatile ("mrc p14, 0, %0, c0, c0, 0" : "=r" (status));
Russell Kingde4533a2006-03-28 10:34:05 +010076 } while (status & 2);
77
Uwe Zeisbergerb2556da2006-05-02 20:40:56 +010078 asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));
Russell Kingde4533a2006-03-28 10:34:05 +010079}
80
Tony Lindgren7d95ded2006-09-20 13:03:34 +010081#endif
82
Russell Kinga0815682006-03-28 10:24:33 +010083#define putc(ch) icedcc_putc(ch)
84#define flush() do { } while (0)
85#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070086
Russell Kinga0815682006-03-28 10:24:33 +010087static void putstr(const char *ptr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088{
Russell Kinga0815682006-03-28 10:24:33 +010089 char c;
90
91 while ((c = *ptr++) != '\0') {
92 if (c == '\n')
93 putc('\r');
94 putc(c);
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 }
Russell Kinga0815682006-03-28 10:24:33 +010096
97 flush();
Linus Torvalds1da177e2005-04-16 15:20:36 -070098}
99
100#endif
101
102#define __ptr_t void *
103
Russell King59f0cb02008-10-27 11:24:09 +0000104#define memzero(s,n) __memzero(s,n)
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106/*
107 * Optimised C version of memzero for the ARM.
108 */
109void __memzero (__ptr_t s, size_t n)
110{
111 union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
112 int i;
113
114 u.vp = s;
115
116 for (i = n >> 5; i > 0; i--) {
117 *u.ulp++ = 0;
118 *u.ulp++ = 0;
119 *u.ulp++ = 0;
120 *u.ulp++ = 0;
121 *u.ulp++ = 0;
122 *u.ulp++ = 0;
123 *u.ulp++ = 0;
124 *u.ulp++ = 0;
125 }
126
127 if (n & 1 << 4) {
128 *u.ulp++ = 0;
129 *u.ulp++ = 0;
130 *u.ulp++ = 0;
131 *u.ulp++ = 0;
132 }
133
134 if (n & 1 << 3) {
135 *u.ulp++ = 0;
136 *u.ulp++ = 0;
137 }
138
139 if (n & 1 << 2)
140 *u.ulp++ = 0;
141
142 if (n & 1 << 1) {
143 *u.ucp++ = 0;
144 *u.ucp++ = 0;
145 }
146
147 if (n & 1)
148 *u.ucp++ = 0;
149}
150
151static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
152 size_t __n)
153{
154 int i = 0;
155 unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
156
157 for (i = __n >> 3; i > 0; i--) {
158 *d++ = *s++;
159 *d++ = *s++;
160 *d++ = *s++;
161 *d++ = *s++;
162 *d++ = *s++;
163 *d++ = *s++;
164 *d++ = *s++;
165 *d++ = *s++;
166 }
167
168 if (__n & 1 << 2) {
169 *d++ = *s++;
170 *d++ = *s++;
171 *d++ = *s++;
172 *d++ = *s++;
173 }
174
175 if (__n & 1 << 1) {
176 *d++ = *s++;
177 *d++ = *s++;
178 }
179
180 if (__n & 1)
181 *d++ = *s++;
182
183 return __dest;
184}
185
186/*
187 * gzip delarations
188 */
189#define OF(args) args
190#define STATIC static
191
192typedef unsigned char uch;
193typedef unsigned short ush;
194typedef unsigned long ulg;
195
196#define WSIZE 0x8000 /* Window size must be at least 32k, */
197 /* and a power of two */
198
199static uch *inbuf; /* input buffer */
200static uch window[WSIZE]; /* Sliding window buffer */
201
202static unsigned insize; /* valid bytes in inbuf */
203static unsigned inptr; /* index of next byte to be processed in inbuf */
204static unsigned outcnt; /* bytes in output buffer */
205
206/* gzip flag byte */
207#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
208#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
209#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
210#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
211#define COMMENT 0x10 /* bit 4 set: file comment present */
212#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
213#define RESERVED 0xC0 /* bit 6,7: reserved */
214
215#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
216
217/* Diagnostic functions */
218#ifdef DEBUG
219# define Assert(cond,msg) {if(!(cond)) error(msg);}
220# define Trace(x) fprintf x
221# define Tracev(x) {if (verbose) fprintf x ;}
222# define Tracevv(x) {if (verbose>1) fprintf x ;}
223# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
224# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
225#else
226# define Assert(cond,msg)
227# define Trace(x)
228# define Tracev(x)
229# define Tracevv(x)
230# define Tracec(c,x)
231# define Tracecv(c,x)
232#endif
233
234static int fill_inbuf(void);
235static void flush_window(void);
236static void error(char *m);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
238extern char input_data[];
239extern char input_data_end[];
240
241static uch *output_data;
242static ulg output_ptr;
243static ulg bytes_out;
244
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245static void error(char *m);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
247static void putstr(const char *);
248
249extern int end;
250static ulg free_mem_ptr;
Thomas Petazzoni2d6ffcc2008-07-25 01:45:44 -0700251static ulg free_mem_end_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252
Thomas Petazzoni2d6ffcc2008-07-25 01:45:44 -0700253#ifdef STANDALONE_DEBUG
254#define NO_INFLATE_MALLOC
255#endif
256
257#define ARCH_HAS_DECOMP_WDOG
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258
259#include "../../../../lib/inflate.c"
260
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261/* ===========================================================================
262 * Fill the input buffer. This is called only when the buffer is empty
263 * and at least one byte is really needed.
264 */
265int fill_inbuf(void)
266{
267 if (insize != 0)
268 error("ran out of input data");
269
270 inbuf = input_data;
271 insize = &input_data_end[0] - &input_data[0];
272
273 inptr = 1;
274 return inbuf[0];
275}
276
277/* ===========================================================================
278 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
279 * (Used for the decompressed data only.)
280 */
281void flush_window(void)
282{
283 ulg c = crc;
284 unsigned n;
285 uch *in, *out, ch;
286
287 in = window;
288 out = &output_data[output_ptr];
289 for (n = 0; n < outcnt; n++) {
290 ch = *out++ = *in++;
291 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
292 }
293 crc = c;
294 bytes_out += (ulg)outcnt;
295 output_ptr += (ulg)outcnt;
296 outcnt = 0;
297 putstr(".");
298}
299
Ben Dooksf8c905d2005-11-08 22:43:05 +0000300#ifndef arch_error
301#define arch_error(x)
302#endif
303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304static void error(char *x)
305{
Ben Dooksf8c905d2005-11-08 22:43:05 +0000306 arch_error(x);
307
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308 putstr("\n\n");
309 putstr(x);
310 putstr("\n\n -- System halted");
311
312 while(1); /* Halt */
313}
314
315#ifndef STANDALONE_DEBUG
316
317ulg
318decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p,
319 int arch_id)
320{
321 output_data = (uch *)output_start; /* Points to kernel start */
322 free_mem_ptr = free_mem_ptr_p;
Thomas Petazzoni2d6ffcc2008-07-25 01:45:44 -0700323 free_mem_end_ptr = free_mem_ptr_end_p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 __machine_arch_type = arch_id;
325
326 arch_decomp_setup();
327
328 makecrc();
329 putstr("Uncompressing Linux...");
330 gunzip();
331 putstr(" done, booting the kernel.\n");
332 return output_ptr;
333}
334#else
335
336char output_buffer[1500*1024];
337
338int main()
339{
340 output_data = output_buffer;
341
342 makecrc();
343 putstr("Uncompressing Linux...");
344 gunzip();
345 putstr("done.\n");
346 return 0;
347}
348#endif
349