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