Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/mn10300/boot/compressed/misc.c
17479 views
1
/* MN10300 Miscellaneous helper routines for kernel decompressor
2
*
3
* Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
4
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5
* Modified by David Howells ([email protected])
6
* - Derived from arch/x86/boot/compressed/misc_32.c
7
*
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public Licence
10
* as published by the Free Software Foundation; either version
11
* 2 of the Licence, or (at your option) any later version.
12
*/
13
#include <linux/compiler.h>
14
#include <asm/serial-regs.h>
15
#include "misc.h"
16
17
#ifndef CONFIG_GDBSTUB_ON_TTYSx
18
/* display 'Uncompressing Linux... ' messages on ttyS0 or ttyS1 */
19
#if 1 /* ttyS0 */
20
#define CYG_DEV_BASE 0xA6FB0000
21
#else /* ttyS1 */
22
#define CYG_DEV_BASE 0xA6FC0000
23
#endif
24
25
#define CYG_DEV_THR (*((volatile __u8*)(CYG_DEV_BASE + 0x00)))
26
#define CYG_DEV_MCR (*((volatile __u8*)(CYG_DEV_BASE + 0x10)))
27
#define SIO_MCR_DTR 0x01
28
#define SIO_MCR_RTS 0x02
29
#define CYG_DEV_LSR (*((volatile __u8*)(CYG_DEV_BASE + 0x14)))
30
#define SIO_LSR_THRE 0x20 /* transmitter holding register empty */
31
#define SIO_LSR_TEMT 0x40 /* transmitter register empty */
32
#define CYG_DEV_MSR (*((volatile __u8*)(CYG_DEV_BASE + 0x18)))
33
#define SIO_MSR_CTS 0x10 /* clear to send */
34
#define SIO_MSR_DSR 0x20 /* data set ready */
35
36
#define LSR_WAIT_FOR(STATE) \
37
do { while (!(CYG_DEV_LSR & SIO_LSR_##STATE)) {} } while (0)
38
#define FLOWCTL_QUERY(LINE) \
39
({ CYG_DEV_MSR & SIO_MSR_##LINE; })
40
#define FLOWCTL_WAIT_FOR(LINE) \
41
do { while (!(CYG_DEV_MSR & SIO_MSR_##LINE)) {} } while (0)
42
#define FLOWCTL_CLEAR(LINE) \
43
do { CYG_DEV_MCR &= ~SIO_MCR_##LINE; } while (0)
44
#define FLOWCTL_SET(LINE) \
45
do { CYG_DEV_MCR |= SIO_MCR_##LINE; } while (0)
46
#endif
47
48
/*
49
* gzip declarations
50
*/
51
52
#define OF(args) args
53
#define STATIC static
54
55
#undef memset
56
#undef memcpy
57
58
static inline void *memset(const void *s, int c, size_t n)
59
{
60
int i;
61
char *ss = (char *) s;
62
63
for (i = 0; i < n; i++)
64
ss[i] = c;
65
return (void *)s;
66
}
67
68
#define memzero(s, n) memset((s), 0, (n))
69
70
static inline void *memcpy(void *__dest, const void *__src, size_t __n)
71
{
72
int i;
73
const char *s = __src;
74
char *d = __dest;
75
76
for (i = 0; i < __n; i++)
77
d[i] = s[i];
78
return __dest;
79
}
80
81
typedef unsigned char uch;
82
typedef unsigned short ush;
83
typedef unsigned long ulg;
84
85
#define WSIZE 0x8000 /* Window size must be at least 32k, and a power of
86
* two */
87
88
static uch *inbuf; /* input buffer */
89
static uch window[WSIZE]; /* sliding window buffer */
90
91
static unsigned insize; /* valid bytes in inbuf */
92
static unsigned inptr; /* index of next byte to be processed in inbuf */
93
static unsigned outcnt; /* bytes in output buffer */
94
95
/* gzip flag byte */
96
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
97
#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
98
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
99
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
100
#define COMMENT 0x10 /* bit 4 set: file comment present */
101
#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
102
#define RESERVED 0xC0 /* bit 6,7: reserved */
103
104
/* Diagnostic functions */
105
#ifdef DEBUG
106
# define Assert(cond, msg) { if (!(cond)) error(msg); }
107
# define Trace(x) fprintf x
108
# define Tracev(x) { if (verbose) fprintf x ; }
109
# define Tracevv(x) { if (verbose > 1) fprintf x ; }
110
# define Tracec(c, x) { if (verbose && (c)) fprintf x ; }
111
# define Tracecv(c, x) { if (verbose > 1 && (c)) fprintf x ; }
112
#else
113
# define Assert(cond, msg)
114
# define Trace(x)
115
# define Tracev(x)
116
# define Tracevv(x)
117
# define Tracec(c, x)
118
# define Tracecv(c, x)
119
#endif
120
121
static int fill_inbuf(void);
122
static void flush_window(void);
123
static void error(const char *) __attribute__((noreturn));
124
static void kputs(const char *);
125
126
static inline unsigned char get_byte(void)
127
{
128
unsigned char ch = inptr < insize ? inbuf[inptr++] : fill_inbuf();
129
130
#if 0
131
char hex[3];
132
hex[0] = ((ch & 0x0f) > 9) ?
133
((ch & 0x0f) + 'A' - 0xa) : ((ch & 0x0f) + '0');
134
hex[1] = ((ch >> 4) > 9) ?
135
((ch >> 4) + 'A' - 0xa) : ((ch >> 4) + '0');
136
hex[2] = 0;
137
kputs(hex);
138
#endif
139
return ch;
140
}
141
142
/*
143
* This is set up by the setup-routine at boot-time
144
*/
145
#define EXT_MEM_K (*(unsigned short *)0x90002)
146
#ifndef STANDARD_MEMORY_BIOS_CALL
147
#define ALT_MEM_K (*(unsigned long *) 0x901e0)
148
#endif
149
#define SCREEN_INFO (*(struct screen_info *)0x90000)
150
151
static long bytes_out;
152
static uch *output_data;
153
static unsigned long output_ptr;
154
155
156
static unsigned long free_mem_ptr = (unsigned long) &end;
157
static unsigned long free_mem_end_ptr = (unsigned long) &end + 0x90000;
158
159
#define INPLACE_MOVE_ROUTINE 0x1000
160
#define LOW_BUFFER_START 0x2000
161
#define LOW_BUFFER_END 0x90000
162
#define LOW_BUFFER_SIZE (LOW_BUFFER_END - LOW_BUFFER_START)
163
#define HEAP_SIZE 0x3000
164
static int high_loaded;
165
static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
166
167
static char *vidmem = (char *)0xb8000;
168
static int lines, cols;
169
170
#define BOOTLOADER_INFLATE
171
#include "../../../../lib/inflate.c"
172
173
static inline void scroll(void)
174
{
175
int i;
176
177
memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
178
for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
179
vidmem[i] = ' ';
180
}
181
182
static inline void kputchar(unsigned char ch)
183
{
184
#ifdef CONFIG_MN10300_UNIT_ASB2305
185
while (SC0STR & SC01STR_TBF)
186
continue;
187
188
if (ch == 0x0a) {
189
SC0TXB = 0x0d;
190
while (SC0STR & SC01STR_TBF)
191
continue;
192
}
193
194
SC0TXB = ch;
195
196
#else
197
while (SC1STR & SC01STR_TBF)
198
continue;
199
200
if (ch == 0x0a) {
201
SC1TXB = 0x0d;
202
while (SC1STR & SC01STR_TBF)
203
continue;
204
}
205
206
SC1TXB = ch;
207
208
#endif
209
}
210
211
static void kputs(const char *s)
212
{
213
#ifdef CONFIG_DEBUG_DECOMPRESS_KERNEL
214
#ifndef CONFIG_GDBSTUB_ON_TTYSx
215
char ch;
216
217
FLOWCTL_SET(DTR);
218
219
while (*s) {
220
LSR_WAIT_FOR(THRE);
221
222
ch = *s++;
223
if (ch == 0x0a) {
224
CYG_DEV_THR = 0x0d;
225
LSR_WAIT_FOR(THRE);
226
}
227
CYG_DEV_THR = ch;
228
}
229
230
FLOWCTL_CLEAR(DTR);
231
#else
232
233
for (; *s; s++)
234
kputchar(*s);
235
236
#endif
237
#endif /* CONFIG_DEBUG_DECOMPRESS_KERNEL */
238
}
239
240
/* ===========================================================================
241
* Fill the input buffer. This is called only when the buffer is empty
242
* and at least one byte is really needed.
243
*/
244
static int fill_inbuf()
245
{
246
if (insize != 0)
247
error("ran out of input data\n");
248
249
inbuf = input_data;
250
insize = input_len;
251
inptr = 1;
252
return inbuf[0];
253
}
254
255
/* ===========================================================================
256
* Write the output window window[0..outcnt-1] and update crc and bytes_out.
257
* (Used for the decompressed data only.)
258
*/
259
static void flush_window_low(void)
260
{
261
ulg c = crc; /* temporary variable */
262
unsigned n;
263
uch *in, *out, ch;
264
265
in = window;
266
out = &output_data[output_ptr];
267
for (n = 0; n < outcnt; n++) {
268
ch = *out++ = *in++;
269
c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
270
}
271
crc = c;
272
bytes_out += (ulg)outcnt;
273
output_ptr += (ulg)outcnt;
274
outcnt = 0;
275
}
276
277
static void flush_window_high(void)
278
{
279
ulg c = crc; /* temporary variable */
280
unsigned n;
281
uch *in, ch;
282
in = window;
283
for (n = 0; n < outcnt; n++) {
284
ch = *output_data++ = *in++;
285
if ((ulg) output_data == LOW_BUFFER_END)
286
output_data = high_buffer_start;
287
c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
288
}
289
crc = c;
290
bytes_out += (ulg)outcnt;
291
outcnt = 0;
292
}
293
294
static void flush_window(void)
295
{
296
if (high_loaded)
297
flush_window_high();
298
else
299
flush_window_low();
300
}
301
302
static void error(const char *x)
303
{
304
kputs("\n\n");
305
kputs(x);
306
kputs("\n\n -- System halted");
307
308
while (1)
309
/* Halt */;
310
}
311
312
#define STACK_SIZE (4096)
313
314
long user_stack[STACK_SIZE];
315
316
struct {
317
long *a;
318
short b;
319
} stack_start = { &user_stack[STACK_SIZE], 0 };
320
321
void setup_normal_output_buffer(void)
322
{
323
#ifdef STANDARD_MEMORY_BIOS_CALL
324
if (EXT_MEM_K < 1024)
325
error("Less than 2MB of memory.\n");
326
#else
327
if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024)
328
error("Less than 2MB of memory.\n");
329
#endif
330
output_data = (char *) 0x100000; /* Points to 1M */
331
}
332
333
struct moveparams {
334
uch *low_buffer_start;
335
int lcount;
336
uch *high_buffer_start;
337
int hcount;
338
};
339
340
void setup_output_buffer_if_we_run_high(struct moveparams *mv)
341
{
342
high_buffer_start = (uch *)(((ulg) &end) + HEAP_SIZE);
343
#ifdef STANDARD_MEMORY_BIOS_CALL
344
if (EXT_MEM_K < (3 * 1024))
345
error("Less than 4MB of memory.\n");
346
#else
347
if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3 * 1024))
348
error("Less than 4MB of memory.\n");
349
#endif
350
mv->low_buffer_start = output_data = (char *) LOW_BUFFER_START;
351
high_loaded = 1;
352
free_mem_end_ptr = (long) high_buffer_start;
353
if (0x100000 + LOW_BUFFER_SIZE > (ulg) high_buffer_start) {
354
high_buffer_start = (uch *)(0x100000 + LOW_BUFFER_SIZE);
355
mv->hcount = 0; /* say: we need not to move high_buffer */
356
} else {
357
mv->hcount = -1;
358
}
359
mv->high_buffer_start = high_buffer_start;
360
}
361
362
void close_output_buffer_if_we_run_high(struct moveparams *mv)
363
{
364
mv->lcount = bytes_out;
365
if (bytes_out > LOW_BUFFER_SIZE) {
366
mv->lcount = LOW_BUFFER_SIZE;
367
if (mv->hcount)
368
mv->hcount = bytes_out - LOW_BUFFER_SIZE;
369
} else {
370
mv->hcount = 0;
371
}
372
}
373
374
#undef DEBUGFLAG
375
#ifdef DEBUGFLAG
376
int debugflag;
377
#endif
378
379
int decompress_kernel(struct moveparams *mv)
380
{
381
#ifdef DEBUGFLAG
382
while (!debugflag)
383
barrier();
384
#endif
385
386
output_data = (char *) CONFIG_KERNEL_TEXT_ADDRESS;
387
388
makecrc();
389
kputs("Uncompressing Linux... ");
390
gunzip();
391
kputs("Ok, booting the kernel.\n");
392
return 0;
393
}
394
395