blob: c5c7dabe5e690ba4f684509b2d87fa9aa67b1a5d [file] [log] [blame] [raw]
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000 Free Software Foundation, 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 program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* 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.
*/
/* Based on "src/misc.c" in etherboot-4.4.2. */
/**************************************************************************
MISC Support Routines
**************************************************************************/
#include "etherboot.h"
/**************************************************************************
SLEEP
**************************************************************************/
void sleep(int secs)
{
long tmo;
for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; )
/* Nothing */;
}
/**************************************************************************
TWIDDLE
**************************************************************************/
void twiddle()
{
static unsigned long lastticks = 0;
static int count=0;
static char tiddles[]="-\\|/";
unsigned long ticks;
if ((ticks = currticks()) < lastticks)
return;
lastticks = ticks+1;
putchar(tiddles[(count++)&3]);
putchar('\b');
}
#if 0
#ifdef ETHERBOOT32
/**************************************************************************
STRCASECMP (not entirely correct, but this will do for our purposes)
**************************************************************************/
int strcasecmp(a,b)
char *a, *b;
{
while (*a && *b && (*a & ~0x20) == (*b & ~0x20)) {a++; b++; }
return((*a & ~0x20) - (*b & ~0x20));
}
#endif /* ETHERBOOT32 */
/**************************************************************************
PRINTF and friends
Formats:
%X - 4 byte ASCII (8 hex digits)
%x - 2 byte ASCII (4 hex digits)
%b - 1 byte ASCII (2 hex digits)
%d - decimal (also %i)
%c - ASCII char
%s - ASCII string
%I - Internet address in x.x.x.x notation
**************************************************************************/
static char hex[]="0123456789ABCDEF";
char *do_printf(buf, fmt, dp)
char *buf, *fmt;
int *dp;
{
register char *p;
char tmp[16];
while (*fmt) {
if (*fmt == '%') { /* switch() uses more space */
fmt++;
if (*fmt == 'X') {
long *lp = (long *)dp;
register long h = *lp++;
dp = (int *)lp;
*(buf++) = hex[(h>>28)& 0x0F];
*(buf++) = hex[(h>>24)& 0x0F];
*(buf++) = hex[(h>>20)& 0x0F];
*(buf++) = hex[(h>>16)& 0x0F];
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'x') {
register int h = *(dp++);
*(buf++) = hex[(h>>12)& 0x0F];
*(buf++) = hex[(h>>8)& 0x0F];
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if (*fmt == 'b') {
register int h = *(dp++);
*(buf++) = hex[(h>>4)& 0x0F];
*(buf++) = hex[h& 0x0F];
}
if ((*fmt == 'd') || (*fmt == 'i')) {
register int dec = *(dp++);
p = tmp;
if (dec < 0) {
*(buf++) = '-';
dec = -dec;
}
do {
*(p++) = '0' + (dec%10);
dec = dec/10;
} while(dec);
while ((--p) >= tmp) *(buf++) = *p;
}
if (*fmt == 'I') {
union {
long l;
unsigned char c[4];
} u;
long *lp = (long *)dp;
u.l = *lp++;
dp = (int *)lp;
buf = sprintf(buf,"%d.%d.%d.%d",
u.c[0], u.c[1], u.c[2], u.c[3]);
}
if (*fmt == 'c')
*(buf++) = *(dp++);
if (*fmt == 's') {
p = (char *)*dp++;
while (*p) *(buf++) = *p++;
}
} else *(buf++) = *fmt;
fmt++;
}
*buf = 0;
return(buf);
}
char *sprintf(buf, fmt, data)
char *fmt, *buf;
int data;
{
return(do_printf(buf,fmt, &data));
}
void printf(fmt,data)
char *fmt;
int data;
{
char buf[120],*p;
p = buf;
do_printf(buf,fmt,&data);
while (*p) putchar(*p++);
}
#ifdef IMAGE_MENU
/**************************************************************************
INET_NTOA - Convert an ascii x.x.x.x to binary form
**************************************************************************/
int inet_ntoa(p, i)
char *p;
in_addr *i;
{
unsigned long ip = 0;
int val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = (ip << 8) | val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
if (*p != '.') return(0);
p++;
ip = (ip << 8) | val;
if (((val = getdec(&p)) < 0) || (val > 255)) return(0);
i->s_addr = htonl((ip << 8) | val);
return(1);
}
#endif /* IMAGE_MENU */
#endif /* 0 */
int getdec(ptr)
char **ptr;
{
char *p = *ptr;
int ret=0;
if ((*p < '0') || (*p > '9')) return(-1);
while ((*p >= '0') && (*p <= '9')) {
ret = ret*10 + (*p - '0');
p++;
}
*ptr = p;
return(ret);
}
#if 0
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keyboard status */
#define K_CMD 0x64 /* keybd ctlr command (write-only) */
#define K_OBUF_FUL 0x01 /* output buffer full */
#define K_IBUF_FUL 0x02 /* input buffer full */
#define KC_CMD_WIN 0xd0 /* read output port */
#define KC_CMD_WOUT 0xd1 /* write output port */
#define KB_A20 0xdf /* enable A20,
enable output buffer full interrupt
enable data line
disable clock line */
#ifndef IBM_L40
static void empty_8042(void)
{
extern void slowdownio();
unsigned long time;
char st;
slowdownio();
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
(st & K_IBUF_FUL)) &&
currticks() < time)
inb(K_RDWR);
}
#endif IBM_L40
/*
* Gate A20 for high memory
*/
void gateA20()
{
#ifdef IBM_L40
outb(0x2, 0x92);
#else IBM_L40
empty_8042();
outb(KC_CMD_WOUT, K_CMD);
empty_8042();
outb(KB_A20, K_RDWR);
empty_8042();
#endif IBM_L40
}
#ifdef ETHERBOOT32
/* Serial console is only implemented in ETHERBOOT32 for now */
void
putchar(int c)
{
#ifdef ANSIESC
handleansi(c);
return;
#endif
if (c == '\n')
putchar('\r');
#ifdef SERIAL_CONSOLE
#if SERIAL_CONSOLE == DUAL
putc(c);
#endif /* SERIAL_CONSOLE == DUAL */
serial_putc(c);
#else
putc(c);
#endif /* SERIAL_CONSOLE */
}
int
getchar(int in_buf)
{
int c=256;
loop:
#ifdef SERIAL_CONSOLE
#if SERIAL_CONSOLE == DUAL
if (ischar())
c = getc();
#endif
if (serial_ischar())
c = serial_getc();
#else
if (ischar())
c = getc();
#endif
if (c==256){
goto loop;
}
if (c == '\r')
c = '\n';
if (c == '\b') {
if (in_buf != 0) {
putchar('\b');
putchar(' ');
} else {
goto loop;
}
}
putchar(c);
return(c);
}
int
iskey(void)
{
int isc;
/*
* Checking the keyboard has the side effect of enabling clock
* interrupts so that bios_tick works. Check the keyboard to
* get this side effect even if we only want the serial status.
*/
#ifdef SERIAL_CONSOLE
#if SERIAL_CONSOLE == DUAL
if (ischar())
return 1;
#endif
if (serial_ischar())
return 1;
#else
if (ischar())
return 1;
#endif
return 0;
}
#endif /* ETHERBOOT32 */
#endif