1/*
2 * arch/sh64/boot/compressed/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 * Adapted for SHmedia from sh by Stuart Menefy, May 2002
10 */
11
12#include <asm/uaccess.h>
13
14/* cache.c */
15#define CACHE_ENABLE      0
16#define CACHE_DISABLE     1
17int cache_control(unsigned int command);
18
19/*
20 * gzip declarations
21 */
22
23#define OF(args)  args
24#define STATIC static
25
26#undef memset
27#undef memcpy
28#define memzero(s, n)     memset ((s), 0, (n))
29
30typedef unsigned char uch;
31typedef unsigned short ush;
32typedef unsigned long ulg;
33
34#define WSIZE 0x8000		/* Window size must be at least 32k, */
35				/* and a power of two */
36
37static uch *inbuf;		/* input buffer */
38static uch window[WSIZE];	/* Sliding window buffer */
39
40static unsigned insize = 0;	/* valid bytes in inbuf */
41static unsigned inptr = 0;	/* index of next byte to be processed in inbuf */
42static unsigned outcnt = 0;	/* bytes in output buffer */
43
44/* gzip flag byte */
45#define ASCII_FLAG   0x01	/* bit 0 set: file probably ASCII text */
46#define CONTINUATION 0x02	/* bit 1 set: continuation of multi-part gzip file */
47#define EXTRA_FIELD  0x04	/* bit 2 set: extra field present */
48#define ORIG_NAME    0x08	/* bit 3 set: original file name present */
49#define COMMENT      0x10	/* bit 4 set: file comment present */
50#define ENCRYPTED    0x20	/* bit 5 set: file is encrypted */
51#define RESERVED     0xC0	/* bit 6,7:   reserved */
52
53#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
54
55/* Diagnostic functions */
56#ifdef DEBUG
57#  define Assert(cond,msg) {if(!(cond)) error(msg);}
58#  define Trace(x) fprintf x
59#  define Tracev(x) {if (verbose) fprintf x ;}
60#  define Tracevv(x) {if (verbose>1) fprintf x ;}
61#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
62#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
63#else
64#  define Assert(cond,msg)
65#  define Trace(x)
66#  define Tracev(x)
67#  define Tracevv(x)
68#  define Tracec(c,x)
69#  define Tracecv(c,x)
70#endif
71
72static int fill_inbuf(void);
73static void flush_window(void);
74static void error(char *m);
75static void gzip_mark(void **);
76static void gzip_release(void **);
77
78extern char input_data[];
79extern int input_len;
80
81static long bytes_out = 0;
82static uch *output_data;
83static unsigned long output_ptr = 0;
84
85static void *malloc(int size);
86static void free(void *where);
87static void error(char *m);
88static void gzip_mark(void **);
89static void gzip_release(void **);
90
91static void puts(const char *);
92
93extern int _text;		/* Defined in vmlinux.lds.S */
94extern int _end;
95static unsigned long free_mem_ptr;
96static unsigned long free_mem_end_ptr;
97
98#define HEAP_SIZE             0x10000
99
100#include "../../../../lib/inflate.c"
101
102static void *malloc(int size)
103{
104	void *p;
105
106	if (size < 0)
107		error("Malloc error\n");
108	if (free_mem_ptr == 0)
109		error("Memory error\n");
110
111	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
112
113	p = (void *) free_mem_ptr;
114	free_mem_ptr += size;
115
116	if (free_mem_ptr >= free_mem_end_ptr)
117		error("\nOut of memory\n");
118
119	return p;
120}
121
122static void free(void *where)
123{				/* Don't care */
124}
125
126static void gzip_mark(void **ptr)
127{
128	*ptr = (void *) free_mem_ptr;
129}
130
131static void gzip_release(void **ptr)
132{
133	free_mem_ptr = (long) *ptr;
134}
135
136void puts(const char *s)
137{
138}
139
140void *memset(void *s, int c, size_t n)
141{
142	int i;
143	char *ss = (char *) s;
144
145	for (i = 0; i < n; i++)
146		ss[i] = c;
147	return s;
148}
149
150void *memcpy(void *__dest, __const void *__src, size_t __n)
151{
152	int i;
153	char *d = (char *) __dest, *s = (char *) __src;
154
155	for (i = 0; i < __n; i++)
156		d[i] = s[i];
157	return __dest;
158}
159
160/* ===========================================================================
161 * Fill the input buffer. This is called only when the buffer is empty
162 * and at least one byte is really needed.
163 */
164static int fill_inbuf(void)
165{
166	if (insize != 0) {
167		error("ran out of input data\n");
168	}
169
170	inbuf = input_data;
171	insize = input_len;
172	inptr = 1;
173	return inbuf[0];
174}
175
176/* ===========================================================================
177 * Write the output window window[0..outcnt-1] and update crc and bytes_out.
178 * (Used for the decompressed data only.)
179 */
180static void flush_window(void)
181{
182	ulg c = crc;		/* temporary variable */
183	unsigned n;
184	uch *in, *out, ch;
185
186	in = window;
187	out = &output_data[output_ptr];
188	for (n = 0; n < outcnt; n++) {
189		ch = *out++ = *in++;
190		c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8);
191	}
192	crc = c;
193	bytes_out += (ulg) outcnt;
194	output_ptr += (ulg) outcnt;
195	outcnt = 0;
196	puts(".");
197}
198
199static void error(char *x)
200{
201	puts("\n\n");
202	puts(x);
203	puts("\n\n -- System halted");
204
205	while (1) ;		/* Halt */
206}
207
208#define STACK_SIZE (4096)
209long __attribute__ ((aligned(8))) user_stack[STACK_SIZE];
210long *stack_start = &user_stack[STACK_SIZE];
211
212void decompress_kernel(void)
213{
214	output_data = (uch *) (CONFIG_MEMORY_START + 0x2000);
215	free_mem_ptr = (unsigned long) &_end;
216	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
217
218	makecrc();
219	puts("Uncompressing Linux... ");
220	cache_control(CACHE_ENABLE);
221	gunzip();
222	puts("\n");
223
224
225	puts("Ok, booting the kernel.\n");
226
227	cache_control(CACHE_DISABLE);
228}
229