linux-bk/arch/ppc/boot/common/misc-common.c
<<
>>
Prefs
   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 */
 554
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.