summaryrefslogtreecommitdiffstats
path: root/arch/ppc/boot/misc.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-06-13 16:29:25 +0000
commitdb7d4daea91e105e3859cf461d7e53b9b77454b2 (patch)
tree9bb65b95440af09e8aca63abe56970dd3360cc57 /arch/ppc/boot/misc.c
parent9c1c01ead627bdda9211c9abd5b758d6c687d8ac (diff)
Merge with Linux 2.2.8.
Diffstat (limited to 'arch/ppc/boot/misc.c')
-rw-r--r--arch/ppc/boot/misc.c695
1 files changed, 356 insertions, 339 deletions
diff --git a/arch/ppc/boot/misc.c b/arch/ppc/boot/misc.c
index 470e1e4a9..15d347df5 100644
--- a/arch/ppc/boot/misc.c
+++ b/arch/ppc/boot/misc.c
@@ -1,7 +1,7 @@
/*
* misc.c
*
- * $Id: misc.c,v 1.53 1998/12/15 17:40:15 cort Exp $
+ * $Id: misc.c,v 1.64 1999/04/30 05:52:46 cort Exp $
*
* Adapted for PowerPC by Gary Thomas
*
@@ -17,13 +17,7 @@
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/mmu.h>
-#ifdef CONFIG_MBX
-#include <asm/mbx.h>
-#endif
-#ifdef CONFIG_FADS
-#include <asm/fads.h>
-#endif
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
#include "ns16550.h"
struct NS16550 *com_port;
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -37,30 +31,18 @@ struct NS16550 *com_port;
*/
char *avail_ram;
char *end_avail;
+extern char _end[];
-/* Because of the limited amount of memory on the MBX, it presents
- * loading problems. The biggest is that we load this boot program
- * into a relatively low memory address, and the Linux kernel Bss often
- * extends into this space when it get loaded. When the kernel starts
- * and zeros the BSS space, it also writes over the information we
- * save here and pass to the kernel (command line and board info).
- * On the MBX we grab some known memory holes to hold this information.
- */
-char cmd_preset[] = "console=tty0 console=ttyS0,9600n8";
-char cmd_buf[256];
-char *cmd_line = cmd_buf;
-
-#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
-char *root_string = "root=/dev/nfs";
-char *nfsaddrs_string = "nfsaddrs=";
-char *nfsroot_string = "nfsroot=";
-char *defroot_string = "/sys/mbxroot";
-int do_ipaddrs(char **cmd_cp, int echo);
-void do_nfsroot(char **cmd_cp, char *dp);
-int strncmp(const char * cs,const char * ct,size_t count);
-char *strrchr(const char * s, int c);
+#ifdef CONFIG_CMDLINE
+#define CMDLINE CONFIG_CMDLINE
+#else
+#define CMDLINE "";
#endif
+char cmd_preset[] = CMDLINE;
+char cmd_buf[256];
+char *cmd_line = cmd_buf;
+int keyb_present = 1; /* keyboard controller is present by default */
RESIDUAL hold_resid_buf;
RESIDUAL *hold_residual = &hold_resid_buf;
unsigned long initrd_start = 0, initrd_end = 0;
@@ -78,6 +60,8 @@ void _bcopy(char *src, char *dst, int len);
void * memcpy(void * __dest, __const void * __src,
int __n);
void gunzip(void *, int, unsigned char *, int *);
+static int _cvt(unsigned long val, char *buf, long radix, char *digits);
+unsigned char inb(int);
void pause()
{
@@ -90,7 +74,6 @@ void exit()
while(1);
}
-#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
static void clear_screen()
{
int i, j;
@@ -113,8 +96,11 @@ static void scroll()
tstc(void)
{
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
- return (CRT_tstc() || NS16550_tstc(com_port));
+#if defined(CONFIG_SERIAL_CONSOLE)
+ if (keyb_present)
+ return (CRT_tstc() || NS16550_tstc(com_port));
+ else
+ NS16550_tstc(com_port);
#else
return (CRT_tstc() );
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -123,10 +109,11 @@ tstc(void)
getc(void)
{
while (1) {
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
if (NS16550_tstc(com_port)) return (NS16550_getc(com_port));
#endif /* CONFIG_SERIAL_CONSOLE */
- if (CRT_tstc()) return (CRT_getc());
+ if (keyb_present)
+ if (CRT_tstc()) return (CRT_getc());
}
}
@@ -135,7 +122,7 @@ putc(const char c)
{
int x,y;
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
NS16550_putc(com_port, c);
if ( c == '\n' ) NS16550_putc(com_port, '\r');
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -149,6 +136,8 @@ putc(const char c)
scroll();
y--;
}
+ } else if (c == '\r') {
+ x = 0;
} else if (c == '\b') {
if (x > 0) {
x--;
@@ -179,7 +168,7 @@ void puts(const char *s)
y = orig_y;
while ( ( c = *s++ ) != '\0' ) {
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
NS16550_putc(com_port, c);
if ( c == '\n' ) NS16550_putc(com_port, '\r');
#endif /* CONFIG_SERIAL_CONSOLE */
@@ -206,42 +195,11 @@ void puts(const char *s)
}
}
+ cursor(x, y);
+
orig_x = x;
orig_y = y;
}
-#else
-/* The MBX is just the serial port.
-*/
-tstc(void)
-{
- return (serial_tstc());
-}
-
-getc(void)
-{
- while (1) {
- if (serial_tstc()) return (serial_getc());
- }
-}
-
-void
-putc(const char c)
-{
- serial_putchar(c);
-}
-
-void puts(const char *s)
-{
- char c;
-
- while ( ( c = *s++ ) != '\0' ) {
- serial_putchar(c);
- if ( c == '\n' )
- serial_putchar('\r');
- }
-}
-
-#endif /* CONFIG_MBX */
void * memcpy(void * __dest, __const void * __src,
int __n)
@@ -354,7 +312,8 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
unsigned char sanity[0x2000];
unsigned long
-decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, RESIDUAL *residual)
+decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+ RESIDUAL *residual, void *OFW_interface)
{
int timer;
extern unsigned long start;
@@ -362,9 +321,13 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
unsigned long i;
BATU *u;
BATL *l;
-#if defined(CONFIG_MBX) || defined(CONFIG_KB)
- char *dp;
-#endif
+ unsigned long TotalMemory;
+ unsigned long orig_MSR;
+ int dev_handle;
+ int mem_info[2];
+ int res, size;
+ unsigned char board_type;
+ unsigned char base_mod;
lines = 25;
cols = 80;
@@ -372,7 +335,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
orig_y = 24;
-#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
/*
* IBM's have the MMU on, so we have to disable it or
* things get really unhappy in the kernel when
@@ -381,42 +343,79 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
*/
flush_instruction_cache();
_put_HID0(_get_HID0() & ~0x0000C000);
- _put_MSR(_get_MSR() & ~0x0030);
- vga_init(0xC0000000);
+ _put_MSR((orig_MSR = _get_MSR()) & ~0x0030);
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#if defined(CONFIG_SERIAL_CONSOLE)
com_port = (struct NS16550 *)NS16550_init(0);
#endif /* CONFIG_SERIAL_CONSOLE */
+ vga_init(0xC0000000);
if (residual)
- memcpy(hold_residual,residual,sizeof(RESIDUAL));
-#else /* CONFIG_MBX */
-
- /* Grab some space for the command line and board info. Since
- * we no longer use the ELF header, but it was loaded, grab
- * that space.
- */
- cmd_line = (char *)(load_addr - 0x10000);
- hold_residual = (RESIDUAL *)(cmd_line + sizeof(cmd_buf));
- /* copy board data */
- if (residual)
- memcpy(hold_residual,residual,sizeof(bd_t));
-#endif /* CONFIG_MBX */
+ {
+ /* Is this Motorola PPCBug? */
+ if ((1 & residual->VitalProductData.FirmwareSupports) &&
+ (1 == residual->VitalProductData.FirmwareSupplier)) {
+ board_type = inb(0x800) & 0xF0;
- /* MBX/prep sometimes put the residual/board info at the end of mem
- * assume 16M for now -- Cort
- * To boot on standard MBX boards with 4M, we can't use initrd,
- * and we have to assume less memory. -- Dan
- */
- if ( INITRD_OFFSET )
- end_avail = (char *)0x01000000;
- else
- end_avail = (char *)0x00400000;
+ /* If this is genesis 2 board then check for no
+ * keyboard controller and more than one processor.
+ */
+ if (board_type == 0xe0) {
+ base_mod = inb(0x803);
+ /* if a MVME2300/2400 or a Sitka then no keyboard */
+ if((base_mod == 0x9) || (base_mod == 0xF9) ||
+ (base_mod == 0xE1)) {
+ keyb_present = 0; /* no keyboard */
+ }
+ }
+ }
+ memcpy(hold_residual,residual,sizeof(RESIDUAL));
+ } else {
+ /* Assume 32M in the absence of more info... */
+ TotalMemory = 0x02000000;
+ /*
+ * This is a 'best guess' check. We want to make sure
+ * we don't try this on a PReP box without OF
+ * -- Cort
+ */
+ while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) )
+ {
+ /* The MMU needs to be on when we call OFW */
+ _put_MSR(orig_MSR);
+ of_init(OFW_interface);
+
+ /* get handle to memory description */
+ res = of_finddevice("/memory@0",
+ &dev_handle);
+ // puthex(res); puts("\n");
+ if (res) break;
+
+ /* get the info */
+ // puts("get info = ");
+ res = of_getprop(dev_handle,
+ "reg",
+ mem_info,
+ sizeof(mem_info),
+ &size);
+ // puthex(res); puts(", info = "); puthex(mem_info[0]);
+ // puts(" "); puthex(mem_info[1]); puts("\n");
+ if (res) break;
+
+ TotalMemory = mem_info[1];
+ break;
+ }
+ hold_residual->TotalMemory = TotalMemory;
+ residual = hold_residual;
+ /* Turn MMU back off */
+ _put_MSR(orig_MSR & ~0x0030);
+ }
- /* let residual data tell us it's higher */
- if ( (unsigned long)residual > 0x00800000 )
- end_avail = (char *)PAGE_ALIGN((unsigned long)residual);
+ /* assume the chunk below 8M is free */
+ end_avail = (char *)0x00800000;
+ /* tell the user where we were loaded at and where we
+ * were relocated to for debugging this process
+ */
puts("loaded at: "); puthex(load_addr);
puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n");
if ( (unsigned long)load_addr != (unsigned long)&start )
@@ -431,20 +430,12 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
{
puts("board data at: "); puthex((unsigned long)residual);
puts(" ");
-#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
- puthex((unsigned long)((unsigned long)residual + sizeof(bd_t)));
-#else
puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL)));
-#endif
puts("\n");
puts("relocated to: ");
puthex((unsigned long)hold_residual);
puts(" ");
-#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
- puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
-#else
puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL)));
-#endif
puts("\n");
}
@@ -460,33 +451,16 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
initrd_end = INITRD_SIZE + initrd_start;
/*
- * setup avail_ram - this is the first part of ram usable
- * by the uncompress code. -- Cort
+ * Find a place to stick the zimage and initrd and
+ * relocate them if we have to. -- Cort
*/
- avail_ram = (char *)PAGE_ALIGN((unsigned long)zimage_start+zimage_size);
- if ( ((load_addr+(num_words*4)) > (unsigned long) avail_ram)
- && (load_addr <= 0x01000000) )
- avail_ram = (char *)(load_addr+(num_words*4));
- if ( (((unsigned long)&start+(num_words*4)) > (unsigned long) avail_ram)
- && (load_addr <= 0x01000000) )
- avail_ram = (char *)((unsigned long)&start+(num_words*4));
-
- /* relocate zimage */
+ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end);
puts("zimage at: "); puthex((unsigned long)zimage_start);
puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n");
- /*
- * don't relocate the zimage if it was loaded above 16M since
- * things get weird if we try to relocate -- Cort
- * We don't relocate zimage on a base MBX board because of
- * insufficient memory. In this case we don't have initrd either,
- * so use that as an indicator. -- Dan
- */
- if (( (unsigned long)zimage_start <= 0x01000000 ) && initrd_start)
+ if ( (unsigned long)zimage_start <= 0x00800000 )
{
- memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size),
- (void *)zimage_start, zimage_size );
- zimage_start = (char *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size);
- end_avail = (char *)zimage_start;
+ memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size );
+ zimage_start = (char *)avail_ram;
puts("relocated to: "); puthex((unsigned long)zimage_start);
puts(" ");
puthex((unsigned long)zimage_size+(unsigned long)zimage_start);
@@ -498,44 +472,24 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
{
puts("initrd at: "); puthex(initrd_start);
puts(" "); puthex(initrd_end); puts("\n");
- /*
- * Memory is really tight on the MBX (we can assume 4M)
- * so put the initrd at the TOP of ram, and set end_avail
- * to right after that.
- *
- * I should do something like this for prep, too and keep
- * a variable end_of_DRAM to keep track of what we think the
- * max ram is.
- * -- Cort
- */
-#if 0
- memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
- (void *)initrd_start,
- INITRD_SIZE );
- initrd_start = PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE);
+#ifdef OMIT
+ avail_ram = (char *)PAGE_ALIGN(
+ (unsigned long)zimage_size+(unsigned long)zimage_start);
+ memcpy ((void *)avail_ram, (void *)initrd_start, INITRD_SIZE );
+ initrd_start = (unsigned long)avail_ram;
initrd_end = initrd_start + INITRD_SIZE;
- end_avail = (char *)initrd_start;
puts("relocated to: "); puthex(initrd_start);
puts(" "); puthex(initrd_end); puts("\n");
-#endif
+#endif
}
-#ifndef CONFIG_MBX
- /* this is safe, just use it */
- /* I don't know why it didn't work for me on the MBX with 20 MB
- * memory. I guess something was saved up there, but I can't
- * figure it out......we are running on luck. -- Dan.
- */
avail_ram = (char *)0x00400000;
- end_avail = (char *)0x00600000;
-#endif
+ end_avail = (char *)0x00800000;
puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" ");
puthex((unsigned long)end_avail); puts("\n");
-
-#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
- CRT_tstc(); /* Forces keyboard to be initialized */
-#endif
+ if (keyb_present)
+ CRT_tstc(); /* Forces keyboard to be initialized */
puts("\nLinux/PPC load: ");
timer = 0;
@@ -550,13 +504,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
cp--;
puts("\b \b");
}
-#ifdef CONFIG_MBX
- } else if (ch == '?') {
- if (!do_ipaddrs(&cp, 1)) {
- *cp++ = ch;
- putc(ch);
- }
-#endif
} else {
*cp++ = ch;
putc(ch);
@@ -567,32 +514,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
udelay(1000); /* 1 msec */
}
*cp = 0;
-#ifdef CONFIG_MBX
- /* The MBX does not currently have any default boot strategy.
- * If the command line is not filled in, we will automatically
- * create the default network boot.
- */
- if (cmd_line[0] == 0) {
- dp = root_string;
- while (*dp != 0)
- *cp++ = *dp++;
- *cp++ = ' ';
-
- dp = nfsaddrs_string;
- while (*dp != 0)
- *cp++ = *dp++;
- dp = cp;
- do_ipaddrs(&cp, 0);
- *cp++ = ' ';
-
- /* Add the server address to the root file system path.
- */
- dp = strrchr(dp, ':');
- dp++;
- do_nfsroot(&cp, dp);
- *cp = 0;
- }
-#endif
puts("\n");
/* mappings on early boot can only handle 16M */
@@ -611,150 +532,6 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, R
return (unsigned long)hold_residual;
}
-#ifdef CONFIG_MBX
-int
-do_ipaddrs(char **cmd_cp, int echo)
-{
- char *cp, *ip, ch;
- unsigned char ipd;
- int i, j, retval;
-
- /* We need to create the string:
- * <my_ip>:<serv_ip>
- */
- cp = *cmd_cp;
- retval = 0;
-
- if ((cp - 9) >= cmd_line) {
- if (strncmp(cp - 9, "nfsaddrs=", 9) == 0) {
- ip = (char *)0xfa000060;
- retval = 1;
- for (j=0; j<2; j++) {
- for (i=0; i<4; i++) {
- ipd = *ip++;
-
- ch = ipd/100;
- if (ch) {
- ch += '0';
- if (echo)
- putc(ch);
- *cp++ = ch;
- ipd -= 100 * (ch - '0');
- }
-
- ch = ipd/10;
- if (ch) {
- ch += '0';
- if (echo)
- putc(ch);
- *cp++ = ch;
- ipd -= 10 * (ch - '0');
- }
-
- ch = ipd + '0';
- if (echo)
- putc(ch);
- *cp++ = ch;
-
- ch = '.';
- if (echo)
- putc(ch);
- *cp++ = ch;
- }
-
- /* At the end of the string, remove the
- * '.' and replace it with a ':'.
- */
- *(cp - 1) = ':';
- if (echo) {
- putc('\b'); putc(':');
- }
- }
-
- /* At the end of the second string, remove the
- * '.' from both the command line and the
- * screen.
- */
- --cp;
- putc('\b'); putc(' '); putc('\b');
- }
- }
- *cmd_cp = cp;
- return(retval);
-}
-
-void
-do_nfsroot(char **cmd_cp, char *dp)
-{
- char *cp, *rp, *ep;
-
- /* The boot argument (i.e /sys/mbxroot/zImage) is stored
- * at offset 0x0078 in NVRAM. We use this path name to
- * construct the root file system path.
- */
- cp = *cmd_cp;
-
- /* build command string.
- */
- rp = nfsroot_string;
- while (*rp != 0)
- *cp++ = *rp++;
-
- /* Add the server address to the path.
- */
- while (*dp != ' ')
- *cp++ = *dp++;
- *cp++ = ':';
-
- rp = (char *)0xfa000078;
- ep = strrchr(rp, '/');
-
- if (ep != 0) {
- while (rp < ep)
- *cp++ = *rp++;
- }
- else {
- rp = defroot_string;
- while (*rp != 0)
- *cp++ = *rp++;
- }
-
- *cmd_cp = cp;
-}
-
-size_t strlen(const char * s)
-{
- const char *sc;
-
- for (sc = s; *sc != '\0'; ++sc)
- /* nothing */;
- return sc - s;
-}
-
-int strncmp(const char * cs,const char * ct,size_t count)
-{
- register signed char __res = 0;
-
- while (count) {
- if ((__res = *cs - *ct++) != 0 || !*cs++)
- break;
- count--;
- }
-
- return __res;
-}
-
-char * strrchr(const char * s, int c)
-{
- const char *p = s + strlen(s);
- do {
- if (*p == (char)c)
- return (char *)p;
- } while (--p >= s);
- return NULL;
-}
-#endif
-
void puthex(unsigned long val)
{
unsigned char buf[10];
@@ -802,3 +579,243 @@ _bcopy(char *src, char *dst, int len)
{
while (len--) *dst++ = *src++;
}
+
+
+#define FALSE 0
+#define TRUE 1
+#include <stdarg.h>
+
+int
+strlen(char *s)
+{
+ int len = 0;
+ while (*s++) len++;
+ return len;
+}
+
+_printk(char const *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = _vprintk(putc, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+
+#define is_digit(c) ((c >= '0') && (c <= '9'))
+
+int
+_vprintk(putc, fmt0, ap)
+int (*putc)();
+const char *fmt0;
+va_list ap;
+{
+ char c, sign, *cp;
+ int left_prec, right_prec, zero_fill, length, 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);
+}
+
+_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;
+ }
+}
+
+_dump_buf(unsigned char *p, int s)
+{
+ _printk("\n");
+ _dump_buf_with_offset(p, s, 0);
+}