2 * Misc. bootloader code (almost) all platforms can use
4 * Author: Johnnie Peters <jpeters@mvista.com>
5 * Editor: Tom Rini <trini@mvista.com>
7 * Derived from arch/ppc/boot/prep/misc.c
9 * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
10 * the terms of the GNU General Public License version 2. This program
11 * is licensed "as is" without any warranty of any kind, whether express
15 #include <stdarg.h> /* for va_ bits */
16 #include <linux/config.h>
17 #include <linux/string.h>
18 #include <linux/zlib.h>
21 /* If we're on a PReP, assume we have a keyboard controller
22 * Also note, if we're not PReP, we assume you are a serial
24 #if defined(CONFIG_PPC_PREP) && defined(CONFIG_VGA_CONSOLE)
25 extern void cursor(int x
, int y
);
26 extern void scroll(void);
28 extern int lines
, cols
;
29 extern int orig_x
, orig_y
;
30 extern int keyb_present
;
31 extern int CRT_tstc(void);
32 extern int CRT_getc(void);
34 int cursor(int x
, int y
) {return 0;}
41 #define keyb_present 0
42 int CRT_tstc(void) {return 0;}
43 int CRT_getc(void) {return 0;}
46 extern char *avail_ram
;
47 extern char *end_avail
;
50 void puts(const char *);
51 void putc(const char c
);
52 void puthex(unsigned long val
);
53 void gunzip(void *, int, unsigned char *, int *);
54 static int _cvt(unsigned long val
, char *buf
, long radix
, char *digits
);
56 void _vprintk(void(*putc
)(const char), const char *fmt0
, va_list ap
);
57 unsigned char *ISA_io
= NULL
;
59 #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
60 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
61 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
62 extern unsigned long com_port
;
64 extern int serial_tstc(unsigned long com_port
);
65 extern unsigned char serial_getc(unsigned long com_port
);
66 extern void serial_putc(unsigned long com_port
, unsigned char c
);
82 #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
83 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
84 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
86 return (CRT_tstc() || serial_tstc(com_port
));
88 return (serial_tstc(com_port
));
97 #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
98 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
99 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
100 if (serial_tstc(com_port
))
101 return (serial_getc(com_port
));
102 #endif /* serial console */
114 #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
115 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
116 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
117 serial_putc(com_port
, c
);
119 serial_putc(com_port
, '\r');
120 #endif /* serial console */
127 if ( ++y
>= lines
) {
131 } else if (c
== '\r') {
133 } else if (c
== '\b') {
138 vidmem
[ ( x
+ cols
* y
) * 2 ] = c
;
141 if ( ++y
>= lines
) {
154 void puts(const char *s
)
162 while ( ( c
= *s
++ ) != '\0' ) {
163 #if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
164 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
165 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
166 serial_putc(com_port
, c
);
167 if ( c
== '\n' ) serial_putc(com_port
, '\r');
168 #endif /* serial console */
172 if ( ++y
>= lines
) {
176 } else if (c
== '\b') {
181 vidmem
[ ( x
+ cols
* y
) * 2 ] = c
;
184 if ( ++y
>= lines
) {
202 puts("\n\n -- System halted");
207 static void *zalloc(unsigned size
)
211 size
= (size
+ 7) & -8;
213 if (avail_ram
> end_avail
) {
214 puts("oops... out of memory\n");
221 #define EXTRA_FIELD 4
224 #define RESERVED 0xe0
226 void gunzip(void *dst
, int dstlen
, unsigned char *src
, int *lenp
)
234 if (src
[2] != Z_DEFLATED
|| (flags
& RESERVED
) != 0) {
235 puts("bad gzipped data\n");
238 if ((flags
& EXTRA_FIELD
) != 0)
239 i
= 12 + src
[10] + (src
[11] << 8);
240 if ((flags
& ORIG_NAME
) != 0)
241 while (src
[i
++] != 0)
243 if ((flags
& COMMENT
) != 0)
244 while (src
[i
++] != 0)
246 if ((flags
& HEAD_CRC
) != 0)
249 puts("gunzip: ran out of data in header\n");
253 /* Initialize ourself. */
254 s
.workspace
= zalloc(zlib_inflate_workspacesize());
255 r
= zlib_inflateInit2(&s
, -MAX_WBITS
);
257 puts("zlib_inflateInit2 returned "); puthex(r
); puts("\n");
261 s
.avail_in
= *lenp
- i
;
263 s
.avail_out
= dstlen
;
264 r
= zlib_inflate(&s
, Z_FINISH
);
265 if (r
!= Z_OK
&& r
!= Z_STREAM_END
) {
266 puts("inflate returned "); puthex(r
); puts("\n");
269 *lenp
= s
.next_out
- (unsigned char *) dst
;
274 puthex(unsigned long val
)
277 unsigned char buf
[10];
279 for (i
= 7; i
>= 0; i
--)
281 buf
[i
] = "0123456789ABCDEF"[val
& 0x0F];
292 _printk(char const *fmt
, ...)
297 _vprintk(putc
, fmt
, ap
);
302 #define is_digit(c) ((c >= '0') && (c <= '9'))
305 _vprintk(void(*putc
)(const char), const char *fmt0
, va_list ap
)
307 char c
, sign
, *cp
= 0;
308 int left_prec
, right_prec
, zero_fill
, length
= 0, pad
, pad_on_right
;
311 while ((c
= *fmt0
++))
316 left_prec
= right_prec
= pad_on_right
= 0;
332 left_prec
= (left_prec
* 10) + (c
- '0');
341 right_prec
= (right_prec
* 10) + (c
- '0');
346 right_prec
= left_prec
;
354 val
= va_arg(ap
, long);
363 length
= _cvt(val
, buf
, 10, "0123456789");
366 length
= _cvt(val
, buf
, 16, "0123456789abcdef");
369 length
= _cvt(val
, buf
, 16, "0123456789ABCDEF");
375 cp
= va_arg(ap
, char *);
379 c
= va_arg(ap
, long /*char*/);
385 pad
= left_prec
- length
;
440 _cvt(unsigned long val
, char *buf
, long radix
, char *digits
)
451 *cp
++ = digits
[val
% radix
];
464 _dump_buf_with_offset(unsigned char *p
, int s
, unsigned char *base
)
467 if ((unsigned int)s
> (unsigned int)p
)
469 s
= (unsigned int)s
- (unsigned int)p
;
475 _printk("%06X: ", (int)p
- (int)base
);
478 _printk("%06X: ", p
);
480 for (i
= 0; i
< 16; i
++)
484 _printk("%02X", p
[i
] & 0xFF);
489 if ((i
% 2) == 1) _printk(" ");
490 if ((i
% 8) == 7) _printk(" ");
493 for (i
= 0; i
< 16; i
++)
498 if ((c
< 0x20) || (c
>= 0x7F)) c
= '.';
512 _dump_buf(unsigned char *p
, int s
)
515 _dump_buf_with_offset(p
, s
, 0);
518 /* Very simple inb/outb routines. We declare ISA_io to be 0 above, and
519 * then modify it on platforms which need to. We do it like this
520 * because on some platforms we give inb/outb an exact location, and
521 * on others it's an offset from a given location. -- Tom
524 void ISA_init(unsigned long base
)
526 ISA_io
= (unsigned char *)base
;
530 outb(int port
, unsigned char val
)
532 /* Ensure I/O operations complete */
533 __asm__
volatile("eieio");
540 /* Ensure I/O operations complete */
541 __asm__
volatile("eieio");
542 return (ISA_io
[port
]);