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