• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
9  * adaptation for Linux/CRIS Axis Communications AB, 1999
10  *
11  */
12 
13 /* where the piggybacked kernel image expects itself to live.
14  * it is the same address we use when we network load an uncompressed
15  * image into DRAM, and it is the address the kernel is linked to live
16  * at by vmlinux.lds.S
17  */
18 
19 #define KERNEL_LOAD_ADR 0x40004000
20 
21 
22 #include <linux/types.h>
23 #include <hwregs/reg_rdwr.h>
24 #include <hwregs/reg_map.h>
25 #include <hwregs/ser_defs.h>
26 #include <hwregs/pinmux_defs.h>
27 #ifdef CONFIG_CRIS_MACH_ARTPEC3
28 #include <hwregs/clkgen_defs.h>
29 #endif
30 
31 /*
32  * gzip declarations
33  */
34 
35 #define OF(args)  args
36 #define STATIC static
37 
38 void* memset(void* s, int c, size_t n);
39 void* memcpy(void* __dest, __const void* __src,
40 	     size_t __n);
41 
42 #define memzero(s, n)     memset ((s), 0, (n))
43 
44 
45 typedef unsigned char  uch;
46 typedef unsigned short ush;
47 typedef unsigned long  ulg;
48 
49 #define WSIZE 0x8000		/* Window size must be at least 32k, */
50 				/* and a power of two */
51 
52 static uch *inbuf;	     /* input buffer */
53 static uch window[WSIZE];    /* Sliding window buffer */
54 
55 unsigned inptr = 0;	/* index of next byte to be processed in inbuf
56 			 * After decompression it will contain the
57 			 * compressed size, and head.S will read it.
58 			 */
59 
60 static unsigned outcnt = 0;  /* bytes in output buffer */
61 
62 /* gzip flag byte */
63 #define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
64 #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
65 #define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
66 #define ORIG_NAME    0x08 /* bit 3 set: original file name present */
67 #define COMMENT      0x10 /* bit 4 set: file comment present */
68 #define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
69 #define RESERVED     0xC0 /* bit 6,7:   reserved */
70 
71 #define get_byte() inbuf[inptr++]
72 
73 /* Diagnostic functions */
74 #ifdef DEBUG
75 #  define Assert(cond,msg) {if(!(cond)) error(msg);}
76 #  define Trace(x) fprintf x
77 #  define Tracev(x) {if (verbose) fprintf x ;}
78 #  define Tracevv(x) {if (verbose>1) fprintf x ;}
79 #  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
80 #  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
81 #else
82 #  define Assert(cond,msg)
83 #  define Trace(x)
84 #  define Tracev(x)
85 #  define Tracevv(x)
86 #  define Tracec(c,x)
87 #  define Tracecv(c,x)
88 #endif
89 
90 static void flush_window(void);
91 static void error(char *m);
92 
93 extern char *input_data;  /* lives in head.S */
94 
95 static long bytes_out;
96 static uch *output_data;
97 static unsigned long output_ptr;
98 
99 static void error(char *m);
100 
101 static void puts(const char *);
102 
103 /* the "heap" is put directly after the BSS ends, at end */
104 
105 extern int _end;
106 static long free_mem_ptr = (long)&_end;
107 static long free_mem_end_ptr;
108 
109 #include "../../../../../lib/inflate.c"
110 
111 /* decompressor info and error messages to serial console */
112 
113 static inline void
serout(const char * s,reg_scope_instances regi_ser)114 serout(const char *s, reg_scope_instances regi_ser)
115 {
116 	reg_ser_rs_stat_din rs;
117 	reg_ser_rw_dout dout = {.data = *s};
118 
119 	do {
120 		rs = REG_RD(ser, regi_ser, rs_stat_din);
121 	}
122 	while (!rs.tr_rdy);/* Wait for transceiver. */
123 
124 	REG_WR(ser, regi_ser, rw_dout, dout);
125 }
126 
127 static void
puts(const char * s)128 puts(const char *s)
129 {
130 #ifndef CONFIG_ETRAX_DEBUG_PORT_NULL
131 	while (*s) {
132 #ifdef CONFIG_ETRAX_DEBUG_PORT0
133 		serout(s, regi_ser0);
134 #endif
135 #ifdef CONFIG_ETRAX_DEBUG_PORT1
136 		serout(s, regi_ser1);
137 #endif
138 #ifdef CONFIG_ETRAX_DEBUG_PORT2
139 		serout(s, regi_ser2);
140 #endif
141 #ifdef CONFIG_ETRAX_DEBUG_PORT3
142 		serout(s, regi_ser3);
143 #endif
144 		*s++;
145 	}
146 /* CONFIG_ETRAX_DEBUG_PORT_NULL */
147 #endif
148 }
149 
150 void*
memset(void * s,int c,size_t n)151 memset(void* s, int c, size_t n)
152 {
153 	int i;
154 	char *ss = (char*)s;
155 
156 	for (i=0;i<n;i++) ss[i] = c;
157 
158 	return s;
159 }
160 
161 void*
memcpy(void * __dest,__const void * __src,size_t __n)162 memcpy(void* __dest, __const void* __src,
163 			    size_t __n)
164 {
165 	int i;
166 	char *d = (char *)__dest, *s = (char *)__src;
167 
168 	for (i=0;i<__n;i++) d[i] = s[i];
169 
170 	return __dest;
171 }
172 
173 /* ===========================================================================
174  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
175  * (Used for the decompressed data only.)
176  */
177 
178 static void
flush_window()179 flush_window()
180 {
181     ulg c = crc;         /* temporary variable */
182     unsigned n;
183     uch *in, *out, ch;
184 
185     in = window;
186     out = &output_data[output_ptr];
187     for (n = 0; n < outcnt; n++) {
188 	    ch = *out++ = *in++;
189 	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
190     }
191     crc = c;
192     bytes_out += (ulg)outcnt;
193     output_ptr += (ulg)outcnt;
194     outcnt = 0;
195 }
196 
197 static void
error(char * x)198 error(char *x)
199 {
200 	puts("\r\n\n");
201 	puts(x);
202 	puts("\r\n\n -- System halted\n");
203 
204 	while(1);	/* Halt */
205 }
206 
207 void
setup_normal_output_buffer(void)208 setup_normal_output_buffer(void)
209 {
210 	output_data = (char *)KERNEL_LOAD_ADR;
211 }
212 
213 static inline void
serial_setup(reg_scope_instances regi_ser)214 serial_setup(reg_scope_instances regi_ser)
215 {
216 	reg_ser_rw_xoff xoff;
217 	reg_ser_rw_tr_ctrl tr_ctrl;
218 	reg_ser_rw_rec_ctrl rec_ctrl;
219 	reg_ser_rw_tr_baud_div tr_baud;
220 	reg_ser_rw_rec_baud_div rec_baud;
221 
222 	/* Turn off XOFF. */
223 	xoff = REG_RD(ser, regi_ser, rw_xoff);
224 
225 	xoff.chr = 0;
226 	xoff.automatic = regk_ser_no;
227 
228 	REG_WR(ser, regi_ser, rw_xoff, xoff);
229 
230 	/* Set baudrate and stopbits. */
231 	tr_ctrl = REG_RD(ser, regi_ser, rw_tr_ctrl);
232 	rec_ctrl = REG_RD(ser, regi_ser, rw_rec_ctrl);
233 	tr_baud = REG_RD(ser, regi_ser, rw_tr_baud_div);
234 	rec_baud = REG_RD(ser, regi_ser, rw_rec_baud_div);
235 
236 	tr_ctrl.stop_bits = 1;	/* 2 stop bits. */
237 	tr_ctrl.en = 1; /* enable transmitter */
238 	rec_ctrl.en = 1; /* enabler receiver */
239 
240 	/*
241 	 * The baudrate setup used to be a bit fishy, but now transmitter and
242 	 * receiver are both set to the intended baud rate, 115200.
243 	 * The magic value is 29.493 MHz.
244 	 */
245 	tr_ctrl.base_freq = regk_ser_f29_493;
246 	rec_ctrl.base_freq = regk_ser_f29_493;
247 	tr_baud.div = (29493000 / 8) / 115200;
248 	rec_baud.div = (29493000 / 8) / 115200;
249 
250 	REG_WR(ser, regi_ser, rw_tr_ctrl, tr_ctrl);
251 	REG_WR(ser, regi_ser, rw_tr_baud_div, tr_baud);
252 	REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
253 	REG_WR(ser, regi_ser, rw_rec_baud_div, rec_baud);
254 }
255 
256 void
decompress_kernel(void)257 decompress_kernel(void)
258 {
259 	char revision;
260 
261 #if defined(CONFIG_ETRAX_DEBUG_PORT1) || \
262     defined(CONFIG_ETRAX_DEBUG_PORT2) || \
263     defined(CONFIG_ETRAX_DEBUG_PORT3)
264 	reg_pinmux_rw_hwprot hwprot;
265 
266 #ifdef CONFIG_CRIS_MACH_ARTPEC3
267 	reg_clkgen_rw_clk_ctrl clk_ctrl;
268 
269 	/* Enable corresponding clock region when serial 1..3 selected */
270 
271 	clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
272 	clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
273 	REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
274 #endif
275 
276 	/* pinmux setup for ports 1..3 */
277 	hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
278 #endif
279 
280 #ifdef CONFIG_ETRAX_DEBUG_PORT0
281 	serial_setup(regi_ser0);
282 #endif
283 #ifdef CONFIG_ETRAX_DEBUG_PORT1
284 	hwprot.ser1 = regk_pinmux_yes;
285 	serial_setup(regi_ser1);
286 #endif
287 #ifdef CONFIG_ETRAX_DEBUG_PORT2
288 	hwprot.ser2 = regk_pinmux_yes;
289 	serial_setup(regi_ser2);
290 #endif
291 #ifdef CONFIG_ETRAX_DEBUG_PORT3
292 	hwprot.ser3 = regk_pinmux_yes;
293 	serial_setup(regi_ser3);
294 #endif
295 #if defined(CONFIG_ETRAX_DEBUG_PORT1) || \
296     defined(CONFIG_ETRAX_DEBUG_PORT2) || \
297     defined(CONFIG_ETRAX_DEBUG_PORT3)
298 	REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
299 #endif
300 
301 	/* input_data is set in head.S */
302 	inbuf = input_data;
303 
304 	setup_normal_output_buffer();
305 
306 	makecrc();
307 
308 	__asm__ volatile ("move $vr,%0" : "=rm" (revision));
309 	if (revision < 32)
310 	{
311 		puts("You need an ETRAX FS to run Linux 2.6/crisv32.\r\n");
312 		while(1);
313 	}
314 
315 	puts("Uncompressing Linux...\r\n");
316 	gunzip();
317 	puts("Done. Now booting the kernel.\r\n");
318 }
319