File: /usr/src/linux/arch/sh/boot/compressed/misc.c

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