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