aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/boot/common/misc-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/boot/common/misc-common.c')
-rw-r--r--arch/ppc/boot/common/misc-common.c553
1 files changed, 553 insertions, 0 deletions
diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
new file mode 100644
index 000000000000..e79e6b3f276e
--- /dev/null
+++ b/arch/ppc/boot/common/misc-common.c
@@ -0,0 +1,553 @@
1/*
2 * arch/ppc/boot/common/misc-common.c
3 *
4 * Misc. bootloader code (almost) all platforms can use
5 *
6 * Author: Johnnie Peters <jpeters@mvista.com>
7 * Editor: Tom Rini <trini@mvista.com>
8 *
9 * Derived from arch/ppc/boot/prep/misc.c
10 *
11 * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
12 * the terms of the GNU General Public License version 2. This program
13 * is licensed "as is" without any warranty of any kind, whether express
14 * or implied.
15 */
16
17#include <stdarg.h> /* for va_ bits */
18#include <linux/config.h>
19#include <linux/string.h>
20#include <linux/zlib.h>
21#include "nonstdio.h"
22
23/* If we're on a PReP, assume we have a keyboard controller
24 * Also note, if we're not PReP, we assume you are a serial
25 * console - Tom */
26#if defined(CONFIG_PPC_PREP) && defined(CONFIG_VGA_CONSOLE)
27extern void cursor(int x, int y);
28extern void scroll(void);
29extern char *vidmem;
30extern int lines, cols;
31extern int orig_x, orig_y;
32extern int keyb_present;
33extern int CRT_tstc(void);
34extern int CRT_getc(void);
35#else
36int cursor(int x, int y) {return 0;}
37void scroll(void) {}
38char vidmem[1];
39#define lines 0
40#define cols 0
41int orig_x = 0;
42int orig_y = 0;
43#define keyb_present 0
44int CRT_tstc(void) {return 0;}
45int CRT_getc(void) {return 0;}
46#endif
47
48extern char *avail_ram;
49extern char *end_avail;
50extern char _end[];
51
52void puts(const char *);
53void putc(const char c);
54void puthex(unsigned long val);
55void gunzip(void *, int, unsigned char *, int *);
56static int _cvt(unsigned long val, char *buf, long radix, char *digits);
57
58void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap);
59unsigned char *ISA_io = NULL;
60
61#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
62 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
63 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
64extern unsigned long com_port;
65
66extern int serial_tstc(unsigned long com_port);
67extern unsigned char serial_getc(unsigned long com_port);
68extern void serial_putc(unsigned long com_port, unsigned char c);
69#endif
70
71void pause(void)
72{
73 puts("pause\n");
74}
75
76void exit(void)
77{
78 puts("exit\n");
79 while(1);
80}
81
82int tstc(void)
83{
84#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
85 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
86 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
87 if(keyb_present)
88 return (CRT_tstc() || serial_tstc(com_port));
89 else
90 return (serial_tstc(com_port));
91#else
92 return CRT_tstc();
93#endif
94}
95
96int getc(void)
97{
98 while (1) {
99#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
100 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
101 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
102 if (serial_tstc(com_port))
103 return (serial_getc(com_port));
104#endif /* serial console */
105 if (keyb_present)
106 if(CRT_tstc())
107 return (CRT_getc());
108 }
109}
110
111void
112putc(const char c)
113{
114 int x,y;
115
116#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
117 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
118 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
119 serial_putc(com_port, c);
120 if ( c == '\n' )
121 serial_putc(com_port, '\r');
122#endif /* serial console */
123
124 x = orig_x;
125 y = orig_y;
126
127 if ( c == '\n' ) {
128 x = 0;
129 if ( ++y >= lines ) {
130 scroll();
131 y--;
132 }
133 } else if (c == '\r') {
134 x = 0;
135 } else if (c == '\b') {
136 if (x > 0) {
137 x--;
138 }
139 } else {
140 vidmem [ ( x + cols * y ) * 2 ] = c;
141 if ( ++x >= cols ) {
142 x = 0;
143 if ( ++y >= lines ) {
144 scroll();
145 y--;
146 }
147 }
148 }
149
150 cursor(x, y);
151
152 orig_x = x;
153 orig_y = y;
154}
155
156void puts(const char *s)
157{
158 int x,y;
159 char c;
160
161 x = orig_x;
162 y = orig_y;
163
164 while ( ( c = *s++ ) != '\0' ) {
165#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
166 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
167 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
168 serial_putc(com_port, c);
169 if ( c == '\n' ) serial_putc(com_port, '\r');
170#endif /* serial console */
171
172 if ( c == '\n' ) {
173 x = 0;
174 if ( ++y >= lines ) {
175 scroll();
176 y--;
177 }
178 } else if (c == '\b') {
179 if (x > 0) {
180 x--;
181 }
182 } else {
183 vidmem [ ( x + cols * y ) * 2 ] = c;
184 if ( ++x >= cols ) {
185 x = 0;
186 if ( ++y >= lines ) {
187 scroll();
188 y--;
189 }
190 }
191 }
192 }
193
194 cursor(x, y);
195
196 orig_x = x;
197 orig_y = y;
198}
199
200void error(char *x)
201{
202 puts("\n\n");
203 puts(x);
204 puts("\n\n -- System halted");
205
206 while(1); /* Halt */
207}
208
209static void *zalloc(unsigned size)
210{
211 void *p = avail_ram;
212
213 size = (size + 7) & -8;
214 avail_ram += size;
215 if (avail_ram > end_avail) {
216 puts("oops... out of memory\n");
217 pause();
218 }
219 return p;
220}
221
222#define HEAD_CRC 2
223#define EXTRA_FIELD 4
224#define ORIG_NAME 8
225#define COMMENT 0x10
226#define RESERVED 0xe0
227
228void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
229{
230 z_stream s;
231 int r, i, flags;
232
233 /* skip header */
234 i = 10;
235 flags = src[3];
236 if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
237 puts("bad gzipped data\n");
238 exit();
239 }
240 if ((flags & EXTRA_FIELD) != 0)
241 i = 12 + src[10] + (src[11] << 8);
242 if ((flags & ORIG_NAME) != 0)
243 while (src[i++] != 0)
244 ;
245 if ((flags & COMMENT) != 0)
246 while (src[i++] != 0)
247 ;
248 if ((flags & HEAD_CRC) != 0)
249 i += 2;
250 if (i >= *lenp) {
251 puts("gunzip: ran out of data in header\n");
252 exit();
253 }
254
255 /* Initialize ourself. */
256 s.workspace = zalloc(zlib_inflate_workspacesize());
257 r = zlib_inflateInit2(&s, -MAX_WBITS);
258 if (r != Z_OK) {
259 puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
260 exit();
261 }
262 s.next_in = src + i;
263 s.avail_in = *lenp - i;
264 s.next_out = dst;
265 s.avail_out = dstlen;
266 r = zlib_inflate(&s, Z_FINISH);
267 if (r != Z_OK && r != Z_STREAM_END) {
268 puts("inflate returned "); puthex(r); puts("\n");
269 exit();
270 }
271 *lenp = s.next_out - (unsigned char *) dst;
272 zlib_inflateEnd(&s);
273}
274
275void
276puthex(unsigned long val)
277{
278
279 unsigned char buf[10];
280 int i;
281 for (i = 7; i >= 0; i--)
282 {
283 buf[i] = "0123456789ABCDEF"[val & 0x0F];
284 val >>= 4;
285 }
286 buf[8] = '\0';
287 puts(buf);
288}
289
290#define FALSE 0
291#define TRUE 1
292
293void
294_printk(char const *fmt, ...)
295{
296 va_list ap;
297
298 va_start(ap, fmt);
299 _vprintk(putc, fmt, ap);
300 va_end(ap);
301 return;
302}
303
304#define is_digit(c) ((c >= '0') && (c <= '9'))
305
306void
307_vprintk(void(*putc)(const char), const char *fmt0, va_list ap)
308{
309 char c, sign, *cp = 0;
310 int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right;
311 char buf[32];
312 long val;
313 while ((c = *fmt0++))
314 {
315 if (c == '%')
316 {
317 c = *fmt0++;
318 left_prec = right_prec = pad_on_right = 0;
319 if (c == '-')
320 {
321 c = *fmt0++;
322 pad_on_right++;
323 }
324 if (c == '0')
325 {
326 zero_fill = TRUE;
327 c = *fmt0++;
328 } else
329 {
330 zero_fill = FALSE;
331 }
332 while (is_digit(c))
333 {
334 left_prec = (left_prec * 10) + (c - '0');
335 c = *fmt0++;
336 }
337 if (c == '.')
338 {
339 c = *fmt0++;
340 zero_fill++;
341 while (is_digit(c))
342 {
343 right_prec = (right_prec * 10) + (c - '0');
344 c = *fmt0++;
345 }
346 } else
347 {
348 right_prec = left_prec;
349 }
350 sign = '\0';
351 switch (c)
352 {
353 case 'd':
354 case 'x':
355 case 'X':
356 val = va_arg(ap, long);
357 switch (c)
358 {
359 case 'd':
360 if (val < 0)
361 {
362 sign = '-';
363 val = -val;
364 }
365 length = _cvt(val, buf, 10, "0123456789");
366 break;
367 case 'x':
368 length = _cvt(val, buf, 16, "0123456789abcdef");
369 break;
370 case 'X':
371 length = _cvt(val, buf, 16, "0123456789ABCDEF");
372 break;
373 }
374 cp = buf;
375 break;
376 case 's':
377 cp = va_arg(ap, char *);
378 length = strlen(cp);
379 break;
380 case 'c':
381 c = va_arg(ap, long /*char*/);
382 (*putc)(c);
383 continue;
384 default:
385 (*putc)('?');
386 }
387 pad = left_prec - length;
388 if (sign != '\0')
389 {
390 pad--;
391 }
392 if (zero_fill)
393 {
394 c = '0';
395 if (sign != '\0')
396 {
397 (*putc)(sign);
398 sign = '\0';
399 }
400 } else
401 {
402 c = ' ';
403 }
404 if (!pad_on_right)
405 {
406 while (pad-- > 0)
407 {
408 (*putc)(c);
409 }
410 }
411 if (sign != '\0')
412 {
413 (*putc)(sign);
414 }
415 while (length-- > 0)
416 {
417 (*putc)(c = *cp++);
418 if (c == '\n')
419 {
420 (*putc)('\r');
421 }
422 }
423 if (pad_on_right)
424 {
425 while (pad-- > 0)
426 {
427 (*putc)(c);
428 }
429 }
430 } else
431 {
432 (*putc)(c);
433 if (c == '\n')
434 {
435 (*putc)('\r');
436 }
437 }
438 }
439}
440
441int
442_cvt(unsigned long val, char *buf, long radix, char *digits)
443{
444 char temp[80];
445 char *cp = temp;
446 int length = 0;
447 if (val == 0)
448 { /* Special case */
449 *cp++ = '0';
450 } else
451 while (val)
452 {
453 *cp++ = digits[val % radix];
454 val /= radix;
455 }
456 while (cp != temp)
457 {
458 *buf++ = *--cp;
459 length++;
460 }
461 *buf = '\0';
462 return (length);
463}
464
465void
466_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
467{
468 int i, c;
469 if ((unsigned int)s > (unsigned int)p)
470 {
471 s = (unsigned int)s - (unsigned int)p;
472 }
473 while (s > 0)
474 {
475 if (base)
476 {
477 _printk("%06X: ", (int)p - (int)base);
478 } else
479 {
480 _printk("%06X: ", p);
481 }
482 for (i = 0; i < 16; i++)
483 {
484 if (i < s)
485 {
486 _printk("%02X", p[i] & 0xFF);
487 } else
488 {
489 _printk(" ");
490 }
491 if ((i % 2) == 1) _printk(" ");
492 if ((i % 8) == 7) _printk(" ");
493 }
494 _printk(" |");
495 for (i = 0; i < 16; i++)
496 {
497 if (i < s)
498 {
499 c = p[i] & 0xFF;
500 if ((c < 0x20) || (c >= 0x7F)) c = '.';
501 } else
502 {
503 c = ' ';
504 }
505 _printk("%c", c);
506 }
507 _printk("|\n");
508 s -= 16;
509 p += 16;
510 }
511}
512
513void
514_dump_buf(unsigned char *p, int s)
515{
516 _printk("\n");
517 _dump_buf_with_offset(p, s, 0);
518}
519
520/* Very simple inb/outb routines. We declare ISA_io to be 0 above, and
521 * then modify it on platforms which need to. We do it like this
522 * because on some platforms we give inb/outb an exact location, and
523 * on others it's an offset from a given location. -- Tom
524 */
525
526void ISA_init(unsigned long base)
527{
528 ISA_io = (unsigned char *)base;
529}
530
531void
532outb(int port, unsigned char val)
533{
534 /* Ensure I/O operations complete */
535 __asm__ volatile("eieio");
536 ISA_io[port] = val;
537}
538
539unsigned char
540inb(int port)
541{
542 /* Ensure I/O operations complete */
543 __asm__ volatile("eieio");
544 return (ISA_io[port]);
545}
546
547/*
548 * Local variables:
549 * c-indent-level: 8
550 * c-basic-offset: 8
551 * tab-width: 8
552 * End:
553 */