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