1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#undef CONFIG_PARAVIRT
18#ifdef CONFIG_X86_64
19#define _LINUX_STRING_H_ 1
20#define __LINUX_BITMAP_H 1
21#endif
22
23#include <linux/linkage.h>
24#include <linux/screen_info.h>
25#include <asm/io.h>
26#include <asm/page.h>
27#include <asm/boot.h>
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114#define OF(args) args
115#define STATIC static
116
117#undef memset
118#undef memcpy
119#define memzero(s, n) memset ((s), 0, (n))
120
121typedef unsigned char uch;
122typedef unsigned short ush;
123typedef unsigned long ulg;
124
125#define WSIZE 0x80000000
126
127
128
129
130
131
132
133static uch *inbuf;
134static uch *window;
135
136static unsigned insize;
137static unsigned inptr;
138static unsigned outcnt;
139
140
141#define ASCII_FLAG 0x01
142#define CONTINUATION 0x02
143#define EXTRA_FIELD 0x04
144#define ORIG_NAME 0x08
145#define COMMENT 0x10
146#define ENCRYPTED 0x20
147#define RESERVED 0xC0
148
149#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf())
150
151
152#ifdef DEBUG
153# define Assert(cond,msg) {if(!(cond)) error(msg);}
154# define Trace(x) fprintf x
155# define Tracev(x) {if (verbose) fprintf x ;}
156# define Tracevv(x) {if (verbose>1) fprintf x ;}
157# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
158# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
159#else
160# define Assert(cond,msg)
161# define Trace(x)
162# define Tracev(x)
163# define Tracevv(x)
164# define Tracec(c,x)
165# define Tracecv(c,x)
166#endif
167
168static int fill_inbuf(void);
169static void flush_window(void);
170static void error(char *m);
171static void gzip_mark(void **);
172static void gzip_release(void **);
173
174
175
176
177static unsigned char *real_mode;
178
179#define RM_EXT_MEM_K (*(unsigned short *)(real_mode + 0x2))
180#ifndef STANDARD_MEMORY_BIOS_CALL
181#define RM_ALT_MEM_K (*(unsigned long *)(real_mode + 0x1e0))
182#endif
183#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
184
185extern unsigned char input_data[];
186extern int input_len;
187
188static long bytes_out = 0;
189
190static void *malloc(int size);
191static void free(void *where);
192
193static void *memset(void *s, int c, unsigned n);
194static void *memcpy(void *dest, const void *src, unsigned n);
195
196static void putstr(const char *);
197
198#ifdef CONFIG_X86_64
199#define memptr long
200#else
201#define memptr unsigned
202#endif
203
204static memptr free_mem_ptr;
205static memptr free_mem_end_ptr;
206
207#ifdef CONFIG_X86_64
208#define HEAP_SIZE 0x7000
209#else
210#define HEAP_SIZE 0x4000
211#endif
212
213static char *vidmem = (char *)0xb8000;
214static int vidport;
215static int lines, cols;
216
217#ifdef CONFIG_X86_NUMAQ
218void *xquad_portio;
219#endif
220
221#include "../../../../lib/inflate.c"
222
223static void *malloc(int size)
224{
225 void *p;
226
227 if (size <0) error("Malloc error");
228 if (free_mem_ptr <= 0) error("Memory error");
229
230 free_mem_ptr = (free_mem_ptr + 3) & ~3;
231
232 p = (void *)free_mem_ptr;
233 free_mem_ptr += size;
234
235 if (free_mem_ptr >= free_mem_end_ptr)
236 error("Out of memory");
237
238 return p;
239}
240
241static void free(void *where)
242{
243}
244
245static void gzip_mark(void **ptr)
246{
247 *ptr = (void *) free_mem_ptr;
248}
249
250static void gzip_release(void **ptr)
251{
252 free_mem_ptr = (memptr) *ptr;
253}
254
255static void scroll(void)
256{
257 int i;
258
259 memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
260 for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
261 vidmem[i] = ' ';
262}
263
264static void putstr(const char *s)
265{
266 int x,y,pos;
267 char c;
268
269#ifdef CONFIG_X86_32
270 if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
271 return;
272#endif
273
274 x = RM_SCREEN_INFO.orig_x;
275 y = RM_SCREEN_INFO.orig_y;
276
277 while ( ( c = *s++ ) != '\0' ) {
278 if ( c == '\n' ) {
279 x = 0;
280 if ( ++y >= lines ) {
281 scroll();
282 y--;
283 }
284 } else {
285 vidmem [(x + cols * y) * 2] = c;
286 if ( ++x >= cols ) {
287 x = 0;
288 if ( ++y >= lines ) {
289 scroll();
290 y--;
291 }
292 }
293 }
294 }
295
296 RM_SCREEN_INFO.orig_x = x;
297 RM_SCREEN_INFO.orig_y = y;
298
299 pos = (x + cols * y) * 2;
300 outb(14, vidport);
301 outb(0xff & (pos >> 9), vidport+1);
302 outb(15, vidport);
303 outb(0xff & (pos >> 1), vidport+1);
304}
305
306static void* memset(void* s, int c, unsigned n)
307{
308 int i;
309 char *ss = s;
310
311 for (i=0;i<n;i++) ss[i] = c;
312 return s;
313}
314
315static void* memcpy(void* dest, const void* src, unsigned n)
316{
317 int i;
318 const char *s = src;
319 char *d = dest;
320
321 for (i=0;i<n;i++) d[i] = s[i];
322 return dest;
323}
324
325
326
327
328
329static int fill_inbuf(void)
330{
331 error("ran out of input data");
332 return 0;
333}
334
335
336
337
338
339static void flush_window(void)
340{
341
342
343
344 ulg c = crc;
345 unsigned n;
346 uch *in, ch;
347
348 in = window;
349 for (n = 0; n < outcnt; n++) {
350 ch = *in++;
351 c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
352 }
353 crc = c;
354 bytes_out += (ulg)outcnt;
355 outcnt = 0;
356}
357
358static void error(char *x)
359{
360 putstr("\n\n");
361 putstr(x);
362 putstr("\n\n -- System halted");
363
364 while (1)
365 asm("hlt");
366}
367
368asmlinkage void decompress_kernel(void *rmode, memptr heap,
369 uch *input_data, unsigned long input_len,
370 uch *output)
371{
372 real_mode = rmode;
373
374 if (RM_SCREEN_INFO.orig_video_mode == 7) {
375 vidmem = (char *) 0xb0000;
376 vidport = 0x3b4;
377 } else {
378 vidmem = (char *) 0xb8000;
379 vidport = 0x3d4;
380 }
381
382 lines = RM_SCREEN_INFO.orig_video_lines;
383 cols = RM_SCREEN_INFO.orig_video_cols;
384
385 window = output;
386 free_mem_ptr = heap;
387 free_mem_end_ptr = heap + HEAP_SIZE;
388 inbuf = input_data;
389 insize = input_len;
390 inptr = 0;
391
392#ifdef CONFIG_X86_64
393 if ((ulg)output & (__KERNEL_ALIGN - 1))
394 error("Destination address not 2M aligned");
395 if ((ulg)output >= 0xffffffffffUL)
396 error("Destination address too large");
397#else
398 if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
399 error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
400 if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
401 error("Destination address too large");
402#ifndef CONFIG_RELOCATABLE
403 if ((u32)output != LOAD_PHYSICAL_ADDR)
404 error("Wrong destination address");
405#endif
406#endif
407
408 makecrc();
409 putstr("\nDecompressing Linux... ");
410 gunzip();
411 putstr("done.\nBooting the kernel.\n");
412 return;
413}
414