xref: /openbmc/linux/arch/nios2/boot/compressed/misc.c (revision 9fb29c73)
1 /*
2  * Copyright (C) 2009 Thomas Chou <thomas@wytron.com.tw>
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  * Based on arch/sh/boot/compressed/misc.c
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27  *
28  */
29 
30 #include <linux/string.h>
31 
32 /*
33  * gzip declarations
34  */
35 #define OF(args)  args
36 #define STATIC static
37 
38 #undef memset
39 #undef memcpy
40 #define memzero(s, n)		memset((s), 0, (n))
41 
42 typedef unsigned char  uch;
43 typedef unsigned short ush;
44 typedef unsigned long  ulg;
45 #define WSIZE 0x8000		/* Window size must be at least 32k, */
46 				/* and a power of two */
47 
48 static uch *inbuf;		/* input buffer */
49 static uch window[WSIZE];	/* Sliding window buffer */
50 
51 static unsigned insize;	/* valid bytes in inbuf */
52 static unsigned inptr;	/* index of next byte to be processed in inbuf */
53 static unsigned outcnt;	/* bytes in output buffer */
54 
55 /* gzip flag byte */
56 #define ASCII_FLAG	0x01 /* bit 0 set: file probably ASCII text */
57 #define CONTINUATION	0x02 /* bit 1 set: continuation of multi-part gzip
58 				file */
59 #define EXTRA_FIELD	0x04 /* bit 2 set: extra field present */
60 #define ORIG_NAME	0x08 /* bit 3 set: original file name present */
61 #define COMMENT		0x10 /* bit 4 set: file comment present */
62 #define ENCRYPTED	0x20 /* bit 5 set: file is encrypted */
63 #define RESERVED	0xC0 /* bit 6,7:   reserved */
64 
65 #define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
66 
67 #ifdef DEBUG
68 #  define Assert(cond, msg) {if (!(cond)) error(msg); }
69 #  define Trace(x) fprintf x
70 #  define Tracev(x) {if (verbose) fprintf x ; }
71 #  define Tracevv(x) {if (verbose > 1) fprintf x ; }
72 #  define Tracec(c, x) {if (verbose && (c)) fprintf x ; }
73 #  define Tracecv(c, x) {if (verbose > 1 && (c)) fprintf x ; }
74 #else
75 #  define Assert(cond, msg)
76 #  define Trace(x)
77 #  define Tracev(x)
78 #  define Tracevv(x)
79 #  define Tracec(c, x)
80 #  define Tracecv(c, x)
81 #endif
82 static int  fill_inbuf(void);
83 static void flush_window(void);
84 static void error(char *m);
85 
86 extern char input_data[];
87 extern int input_len;
88 
89 static long bytes_out;
90 static uch *output_data;
91 static unsigned long output_ptr;
92 
93 #include "console.c"
94 
95 static void error(char *m);
96 
97 int puts(const char *);
98 
99 extern int _end;
100 static unsigned long free_mem_ptr;
101 static unsigned long free_mem_end_ptr;
102 
103 #define HEAP_SIZE			0x10000
104 
105 #include "../../../../lib/inflate.c"
106 
107 void *memset(void *s, int c, size_t n)
108 {
109 	int i;
110 	char *ss = (char *)s;
111 
112 	for (i = 0; i < n; i++)
113 		ss[i] = c;
114 	return s;
115 }
116 
117 void *memcpy(void *__dest, __const void *__src, size_t __n)
118 {
119 	int i;
120 	char *d = (char *)__dest, *s = (char *)__src;
121 
122 	for (i = 0; i < __n; i++)
123 		d[i] = s[i];
124 	return __dest;
125 }
126 
127 /*
128  * Fill the input buffer. This is called only when the buffer is empty
129  * and at least one byte is really needed.
130  */
131 static int fill_inbuf(void)
132 {
133 	if (insize != 0)
134 		error("ran out of input data");
135 
136 	inbuf = input_data;
137 	insize = input_len;
138 	inptr = 1;
139 	return inbuf[0];
140 }
141 
142 /*
143  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
144  * (Used for the decompressed data only.)
145  */
146 static void flush_window(void)
147 {
148 	ulg c = crc;	/* temporary variable */
149 	unsigned n;
150 	uch *in, *out, ch;
151 
152 	in = window;
153 	out = &output_data[output_ptr];
154 	for (n = 0; n < outcnt; n++) {
155 		ch = *out++ = *in++;
156 		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
157 	}
158 	crc = c;
159 	bytes_out += (ulg)outcnt;
160 	output_ptr += (ulg)outcnt;
161 	outcnt = 0;
162 }
163 
164 static void error(char *x)
165 {
166 	puts("\nERROR\n");
167 	puts(x);
168 	puts("\n\n -- System halted");
169 
170 	while (1)	/* Halt */
171 		;
172 }
173 
174 void decompress_kernel(void)
175 {
176 	output_data = (void *) (CONFIG_NIOS2_MEM_BASE |
177 				CONFIG_NIOS2_KERNEL_REGION_BASE);
178 	output_ptr = 0;
179 	free_mem_ptr = (unsigned long)&_end;
180 	free_mem_end_ptr = free_mem_ptr + HEAP_SIZE;
181 
182 	console_init();
183 	makecrc();
184 	puts("Uncompressing Linux... ");
185 	gunzip();
186 	puts("Ok, booting the kernel.\n");
187 }
188