?? misc-common.c
字號:
/* * arch/ppc/boot/common/misc-common.c * * Misc. bootloader code (almost) all platforms can use * * Author: Johnnie Peters <jpeters@mvista.com> * Editor: Tom Rini <trini@mvista.com> * * Derived from arch/ppc/boot/prep/misc.c * * Copyright 2000-2001 MontaVista Software Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */#include <stdarg.h> /* for va_ bits */#include <linux/config.h>#include "zlib.h"#include "nonstdio.h"/* If we're on a ALL_PPC, assume we have a keyboard controller * Also note, if we're not ALL_PPC, we assume you are a serial * console - Tom */#if defined(CONFIG_ALL_PPC) && defined(CONFIG_VGA_CONSOLE)extern void cursor(int x, int y);extern void scroll(void);extern char *vidmem;extern int lines, cols;extern int orig_x, orig_y;extern int keyb_present;extern int CRT_tstc(void);extern int CRT_getc(void);#elseint cursor(int x, int y) {return 0;}void scroll(void) {}char vidmem[1];#define lines 0#define cols 0int orig_x = 0;int orig_y = 0;#define keyb_present 0int CRT_tstc(void) {return 0;}int CRT_getc(void) {return 0;}#endifextern char *avail_ram;extern char *end_avail;extern char _end[];void puts(const char *);void putc(const char c);void puthex(unsigned long val);void _bcopy(char *src, char *dst, int len);void gunzip(void *, int, unsigned char *, int *);static int _cvt(unsigned long val, char *buf, long radix, char *digits);void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap);unsigned char *ISA_io = NULL;#if defined(CONFIG_SERIAL_CONSOLE)extern unsigned long com_port;extern int serial_tstc(unsigned long com_port);extern unsigned char serial_getc(unsigned long com_port);extern void serial_putc(unsigned long com_port, unsigned char c);#endifvoid pause(void){ puts("pause\n");}void exit(void){ puts("exit\n"); while(1); }int tstc(void){#if defined(CONFIG_SERIAL_CONSOLE) if(keyb_present) return (CRT_tstc() || serial_tstc(com_port)); else return (serial_tstc(com_port));#else return CRT_tstc();#endif}int getc(void){ while (1) {#if defined(CONFIG_SERIAL_CONSOLE) if (serial_tstc(com_port)) return (serial_getc(com_port));#endif /* CONFIG_SERIAL_CONSOLE */ if (keyb_present) if(CRT_tstc()) return (CRT_getc()); }}void putc(const char c){ int x,y;#if defined(CONFIG_SERIAL_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r');#endif /* CONFIG_SERIAL_CONSOLE */ x = orig_x; y = orig_y; if ( c == '\n' ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } else if (c == '\r') { x = 0; } else if (c == '\b') { if (x > 0) { x--; } } else { vidmem [ ( x + cols * y ) * 2 ] = c; if ( ++x >= cols ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } } cursor(x, y); orig_x = x; orig_y = y;}void puts(const char *s){ int x,y; char c; x = orig_x; y = orig_y; while ( ( c = *s++ ) != '\0' ) {#if defined(CONFIG_SERIAL_CONSOLE) serial_putc(com_port, c); if ( c == '\n' ) serial_putc(com_port, '\r');#endif /* CONFIG_SERIAL_CONSOLE */ if ( c == '\n' ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } else if (c == '\b') { if (x > 0) { x--; } } else { vidmem [ ( x + cols * y ) * 2 ] = c; if ( ++x >= cols ) { x = 0; if ( ++y >= lines ) { scroll(); y--; } } } } cursor(x, y); orig_x = x; orig_y = y;}void error(char *x){ puts("\n\n"); puts(x); puts("\n\n -- System halted"); while(1); /* Halt */}void *zalloc(void *x, unsigned items, unsigned size){ void *p = avail_ram; size *= items; size = (size + 7) & -8; avail_ram += size; if (avail_ram > end_avail) { puts("oops... out of memory\n"); pause(); } return p;}void zfree(void *x, void *addr, unsigned nb){}#define HEAD_CRC 2#define EXTRA_FIELD 4#define ORIG_NAME 8#define COMMENT 0x10#define RESERVED 0xe0#define DEFLATED 8void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp){ z_stream s; int r, i, flags; /* skip header */ i = 10; flags = src[3]; if (src[2] != DEFLATED || (flags & RESERVED) != 0) { puts("bad gzipped data\n"); exit(); } if ((flags & EXTRA_FIELD) != 0) i = 12 + src[10] + (src[11] << 8); if ((flags & ORIG_NAME) != 0) while (src[i++] != 0) ; if ((flags & COMMENT) != 0) while (src[i++] != 0) ; if ((flags & HEAD_CRC) != 0) i += 2; if (i >= *lenp) { puts("gunzip: ran out of data in header\n"); exit(); } s.zalloc = zalloc; s.zfree = zfree; r = inflateInit2(&s, -MAX_WBITS); if (r != Z_OK) { puts("inflateInit2 returned "); puthex(r); puts("\n"); exit(); } s.next_in = src + i; s.avail_in = *lenp - i; s.next_out = dst; s.avail_out = dstlen; r = inflate(&s, Z_FINISH); if (r != Z_OK && r != Z_STREAM_END) { puts("inflate returned "); puthex(r); puts("\n"); exit(); } *lenp = s.next_out - (unsigned char *) dst; inflateEnd(&s);}voidputhex(unsigned long val){ unsigned char buf[10]; int i; for (i = 7; i >= 0; i--) { buf[i] = "0123456789ABCDEF"[val & 0x0F]; val >>= 4; } buf[8] = '\0'; puts(buf);}#define FALSE 0#define TRUE 1void_printk(char const *fmt, ...){ va_list ap; va_start(ap, fmt); _vprintk(putc, fmt, ap); va_end(ap); return;}#define is_digit(c) ((c >= '0') && (c <= '9'))void_vprintk(void(*putc)(const char), const char *fmt0, va_list ap){ char c, sign, *cp = 0; int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right; char buf[32]; long val; while ((c = *fmt0++)) { if (c == '%') { c = *fmt0++; left_prec = right_prec = pad_on_right = 0; if (c == '-') { c = *fmt0++; pad_on_right++; } if (c == '0') { zero_fill = TRUE; c = *fmt0++; } else { zero_fill = FALSE; } while (is_digit(c)) { left_prec = (left_prec * 10) + (c - '0'); c = *fmt0++; } if (c == '.') { c = *fmt0++; zero_fill++; while (is_digit(c)) { right_prec = (right_prec * 10) + (c - '0'); c = *fmt0++; } } else { right_prec = left_prec; } sign = '\0'; switch (c) { case 'd': case 'x': case 'X': val = va_arg(ap, long); switch (c) { case 'd': if (val < 0) { sign = '-'; val = -val; } length = _cvt(val, buf, 10, "0123456789"); break; case 'x': length = _cvt(val, buf, 16, "0123456789abcdef"); break; case 'X': length = _cvt(val, buf, 16, "0123456789ABCDEF"); break; } cp = buf; break; case 's': cp = va_arg(ap, char *); length = strlen(cp); break; case 'c': c = va_arg(ap, long /*char*/); (*putc)(c); continue; default: (*putc)('?'); } pad = left_prec - length; if (sign != '\0') { pad--; } if (zero_fill) { c = '0'; if (sign != '\0') { (*putc)(sign); sign = '\0'; } } else { c = ' '; } if (!pad_on_right) { while (pad-- > 0) { (*putc)(c); } } if (sign != '\0') { (*putc)(sign); } while (length-- > 0) { (*putc)(c = *cp++); if (c == '\n') { (*putc)('\r'); } } if (pad_on_right) { while (pad-- > 0) { (*putc)(c); } } } else { (*putc)(c); if (c == '\n') { (*putc)('\r'); } } }}int_cvt(unsigned long val, char *buf, long radix, char *digits){ char temp[80]; char *cp = temp; int length = 0; if (val == 0) { /* Special case */ *cp++ = '0'; } else while (val) { *cp++ = digits[val % radix]; val /= radix; } while (cp != temp) { *buf++ = *--cp; length++; } *buf = '\0'; return (length);}void_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base){ int i, c; if ((unsigned int)s > (unsigned int)p) { s = (unsigned int)s - (unsigned int)p; } while (s > 0) { if (base) { _printk("%06X: ", (int)p - (int)base); } else { _printk("%06X: ", p); } for (i = 0; i < 16; i++) { if (i < s) { _printk("%02X", p[i] & 0xFF); } else { _printk(" "); } if ((i % 2) == 1) _printk(" "); if ((i % 8) == 7) _printk(" "); } _printk(" |"); for (i = 0; i < 16; i++) { if (i < s) { c = p[i] & 0xFF; if ((c < 0x20) || (c >= 0x7F)) c = '.'; } else { c = ' '; } _printk("%c", c); } _printk("|\n"); s -= 16; p += 16; }}void_dump_buf(unsigned char *p, int s){ _printk("\n"); _dump_buf_with_offset(p, s, 0);}/* Very simple inb/outb routines. We declare ISA_io to be 0 above, and * then modify it on platforms which need to. We do it like this * because on some platforms we give inb/outb an exact location, and * on others it's an offset from a given location. -- Tom */voidoutb(int port, unsigned char val){ /* Ensure I/O operations complete */ __asm__ volatile("eieio"); ISA_io[port] = val;}unsigned charinb(int port){ /* Ensure I/O operations complete */ __asm__ volatile("eieio"); return (ISA_io[port]);}/* * Local variables: * c-indent-level: 8 * c-basic-offset: 8 * tab-width: 8 * End: */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -