mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
614 lines
8.9 KiB
614 lines
8.9 KiB
/*
|
|
*
|
|
* Copyright (c) 1994 FirmWorks, Mountain View CA USA. All rights reserved.
|
|
* Copyright (c) 1995 FirePower Systems, Inc.
|
|
* Copyright (c) 1996 FirePower Systems, Inc.
|
|
*
|
|
* $RCSfile: vrlib.c $
|
|
* $Revision: 1.14 $
|
|
* $Date: 1996/06/27 18:36:55 $
|
|
* $Locker: $
|
|
*/
|
|
|
|
#include "veneer.h"
|
|
|
|
STATIC VOID doprnt(VOID (*)(), char *, va_list);
|
|
STATIC VOID printbase(VOID (*)(), ULONG x, int base);
|
|
|
|
int
|
|
get_bool_prop(phandle node, char *key)
|
|
{
|
|
return(OFGetproplen(node, key) != -1);
|
|
}
|
|
|
|
int
|
|
decode_int(UCHAR *p)
|
|
{
|
|
ULONG i = *p++ << 8;
|
|
i = (i + *p++) << 8;
|
|
i = (i + *p++) << 8;
|
|
return (i + *p);
|
|
}
|
|
|
|
int
|
|
get_int_prop(phandle node, char *key)
|
|
{
|
|
int res;
|
|
char buf[sizeof(int)];
|
|
|
|
res = OFGetprop(node, key, buf, sizeof(int));
|
|
if (res != sizeof(int)) {
|
|
return(-1);
|
|
}
|
|
/*
|
|
* The NT veneer is always little-endian.
|
|
*/
|
|
return(decode_int((UCHAR *) buf));
|
|
}
|
|
|
|
reg *
|
|
decode_reg(UCHAR *buf, int buflen, int addr_cells, int size_cells)
|
|
{
|
|
static reg staticreg;
|
|
reg *r = &staticreg;
|
|
|
|
bzero((PCHAR) r, sizeof(reg));
|
|
|
|
if (buflen < addr_cells + size_cells) {
|
|
fatal("reg property smaller than #address-cell plus #size-cells\n");
|
|
}
|
|
|
|
r->lo = decode_int(buf + ((addr_cells-1) * 4));
|
|
r->hi = decode_int(buf);
|
|
r->size = decode_int(buf + ((addr_cells + size_cells - 1) * 4));
|
|
|
|
return (r);
|
|
}
|
|
|
|
reg *
|
|
get_reg_prop(phandle node, char *key, int index)
|
|
{
|
|
int res;
|
|
char *buf;
|
|
reg *regp;
|
|
int len = OFGetproplen(node, key);
|
|
int addr_cells, size_cells, offset;
|
|
|
|
buf = (char *)malloc(len);
|
|
res = OFGetprop(node, key, buf, len);
|
|
if (res != len) {
|
|
fatal("get_reg_prop(node %x, key '%s', len %x) returned %x\n",
|
|
node, key, len, res);
|
|
free(buf);
|
|
return ((reg *) 0);
|
|
}
|
|
|
|
|
|
addr_cells = get_int_prop(OFParent(node), "#address-cells");
|
|
if (addr_cells < 0) {
|
|
addr_cells = 2;
|
|
}
|
|
size_cells = get_int_prop(OFParent(node), "#size-cells");
|
|
if (size_cells < 0) {
|
|
size_cells = 1;
|
|
}
|
|
|
|
offset = index * (addr_cells + size_cells) * 4;
|
|
key = buf + offset;
|
|
len -= offset;
|
|
if (len) {
|
|
debug(VRDBG_TEST, "key %x len %x\n", key, len);
|
|
regp = decode_reg(key, len, addr_cells, size_cells);
|
|
} else {
|
|
debug(VRDBG_TEST, "returning NULL regp\n");
|
|
regp = NULL;
|
|
}
|
|
|
|
free(buf);
|
|
return (regp);
|
|
}
|
|
|
|
char *
|
|
get_str_prop(phandle node, char *key, allocflag alloc)
|
|
{
|
|
int len, res;
|
|
static char *priv_buf, priv_buf_len = 0;
|
|
char *cp;
|
|
|
|
len = OFGetproplen(node, key);
|
|
if (len == -1 || len == 0) {
|
|
return((char *) 0);
|
|
}
|
|
|
|
/*
|
|
* Leave room for a null terminator, on the off chance that the
|
|
* property isn't null-terminated.
|
|
*/
|
|
len += 1;
|
|
if (alloc == ALLOC) {
|
|
cp = (char *) zalloc(len);
|
|
} else {
|
|
if (len > priv_buf_len) {
|
|
if (priv_buf_len) {
|
|
free(priv_buf);
|
|
}
|
|
priv_buf = (char *) zalloc(len);
|
|
priv_buf_len = len;
|
|
} else {
|
|
bzero(priv_buf, len);
|
|
}
|
|
cp = priv_buf;
|
|
}
|
|
len -= 1;
|
|
|
|
res = OFGetprop(node, key, cp, len);
|
|
if (res != len) {
|
|
fatal( "get_str_prop(node %x, key '%s', len %x) returned len %x\n",
|
|
node, key, len, res);
|
|
return((char *) 0);
|
|
}
|
|
return(cp);
|
|
}
|
|
|
|
int
|
|
strcmp(const char *s, const char *t)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; s[i] == t[i]; ++i) {
|
|
if (s[i] == '\0') {
|
|
return (0);
|
|
}
|
|
}
|
|
return((int) (s[i] - t[i]));
|
|
}
|
|
|
|
|
|
int
|
|
strncmp(const char *s, const char *t, size_t len)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; (s[i] == t[i]) && (i != (int) len); ++i) {
|
|
if (s[i] == '\0') {
|
|
return (0);
|
|
}
|
|
}
|
|
if (i == (int) len) {
|
|
return(0);
|
|
}
|
|
return((int) (s[i] - t[i]));
|
|
}
|
|
|
|
int
|
|
strncasecmp(const char *s, const char *t, size_t len)
|
|
{
|
|
int i;
|
|
char s1 = 0, t1 = 0;
|
|
|
|
for (i = 0; i != (int) len; ++i) {
|
|
if (s[i] == '\0') {
|
|
return (0);
|
|
}
|
|
s1 = s[i];
|
|
if (s1 >= 'a' && s1 <= 'z') {
|
|
s1 -= 0x20;
|
|
}
|
|
t1 = t[i];
|
|
if (t1 >= 'a' && t1 <= 'z') {
|
|
t1 -= 0x20;
|
|
}
|
|
if (s1 == t1) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == (int) len) {
|
|
return(0);
|
|
}
|
|
return((int) (s1 - t1));
|
|
}
|
|
|
|
size_t
|
|
strlen(const char *s)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; s[i] != '\0'; ++i) {
|
|
;
|
|
}
|
|
return((size_t) i);
|
|
}
|
|
|
|
char *
|
|
strcpy(char *to, const char *from)
|
|
{
|
|
int i = 0;
|
|
|
|
while (to[i] = from[i]) {
|
|
i += 1;
|
|
}
|
|
return(to);
|
|
}
|
|
|
|
char *
|
|
strcat(char *to, const char *from)
|
|
{
|
|
char *ret = to;
|
|
|
|
while (*to) {
|
|
to += 1;
|
|
}
|
|
strcpy(to, from);
|
|
return (ret);
|
|
}
|
|
|
|
VOID
|
|
bcopy(char *from, char *to, int len)
|
|
{
|
|
while (len--) {
|
|
*to++ = *from++;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
bzero(char *cp, int len)
|
|
{
|
|
while (len--) {
|
|
*(cp + len) = 0;
|
|
}
|
|
}
|
|
|
|
VOID *
|
|
zalloc(int size)
|
|
{
|
|
VOID *vp;
|
|
|
|
vp = malloc(size);
|
|
bzero(vp, size);
|
|
return (vp);
|
|
}
|
|
|
|
VOID
|
|
sleep(ULONG delay)
|
|
{
|
|
delay += VrGetRelativeTime();
|
|
while (VrGetRelativeTime() < delay) {
|
|
;
|
|
}
|
|
}
|
|
|
|
int
|
|
claim(void *adr, int bytes)
|
|
{
|
|
return(OFClaim((PCHAR) MAP(adr), bytes, 0));
|
|
}
|
|
|
|
VOID *
|
|
alloc(int size, int align)
|
|
{
|
|
return((VOID *) OFClaim(0, size, align));
|
|
}
|
|
|
|
int
|
|
atoi(char *s)
|
|
{
|
|
int temp = 0, base = 10;
|
|
char *start;
|
|
|
|
if (*s == '0') {
|
|
++s;
|
|
if (*s == 'x') {
|
|
++s;
|
|
base = 16;
|
|
} else {
|
|
base = 8;
|
|
}
|
|
}
|
|
start = s;
|
|
again:
|
|
while (*s) {
|
|
switch (*s) {
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
case '5': case '6': case '7': case '8': case '9':
|
|
temp = (temp * base) + (*s++ - '0');
|
|
break;
|
|
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
|
|
if (base == 10) {
|
|
base = 16;
|
|
temp = 0;
|
|
s = start;
|
|
goto again;
|
|
}
|
|
temp = (temp * base) + (*s++ - 'a' + 10);
|
|
break;
|
|
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
|
|
if (base == 10) {
|
|
base = 16;
|
|
temp = 0;
|
|
s = start;
|
|
goto again;
|
|
}
|
|
temp = (temp * base) + (*s++ - 'A' + 10);
|
|
break;
|
|
default:
|
|
return (temp);
|
|
}
|
|
}
|
|
return (temp);
|
|
}
|
|
|
|
char *
|
|
index(char *s, int c)
|
|
{
|
|
while (*s) {
|
|
if (*s == c) {
|
|
return (s);
|
|
}
|
|
++s;
|
|
}
|
|
return ((char *) 0);
|
|
}
|
|
|
|
char *
|
|
strcsep(char *s, const char sep)
|
|
{
|
|
static char *saved_str = NULL;
|
|
char *temp;
|
|
|
|
if (s != NULL) {
|
|
saved_str = s;
|
|
}
|
|
if (saved_str == NULL) {
|
|
return(NULL);
|
|
}
|
|
s = index(saved_str, sep);
|
|
if (s != NULL) {
|
|
*s++ = '\0';
|
|
}
|
|
temp = saved_str;
|
|
saved_str = s;
|
|
return(temp);
|
|
}
|
|
|
|
char *
|
|
strctok(char *s, const char sep)
|
|
{
|
|
static char *saved_str = NULL;
|
|
char *temp;
|
|
|
|
if (s != NULL) {
|
|
saved_str = s;
|
|
}
|
|
if (saved_str == NULL) {
|
|
return(NULL);
|
|
}
|
|
s = index(saved_str, sep);
|
|
if (s != NULL) {
|
|
*s++ = '\0';
|
|
while (*s && (*s == sep)) {
|
|
++s;
|
|
}
|
|
}
|
|
temp = saved_str;
|
|
saved_str = s;
|
|
return(temp);
|
|
}
|
|
|
|
char *
|
|
capitalize(char *s)
|
|
{
|
|
char *p;
|
|
|
|
p = s;
|
|
while (*p) {
|
|
*p = islower(*p) ? toupper(*p) : *p;
|
|
++p;
|
|
}
|
|
return(s);
|
|
}
|
|
|
|
|
|
|
|
STATIC ihandle stdout = 0;
|
|
STATIC char outbuf[128];
|
|
STATIC int outbufc = 0;
|
|
|
|
VOID
|
|
putchar(char c)
|
|
{
|
|
phandle ph;
|
|
|
|
if (stdout == 0) {
|
|
ph = OFFinddevice("/chosen");
|
|
if (ph == -1) {
|
|
/* What to do here?!? */
|
|
while (1) {
|
|
;
|
|
}
|
|
}
|
|
stdout = get_int_prop(ph, "stdout");
|
|
}
|
|
|
|
if (c == '\n') {
|
|
outbuf[outbufc++] = '\r';
|
|
}
|
|
outbuf[outbufc++] = c;
|
|
if ((c == '\n') || (outbufc == 127)) {
|
|
OFWrite(stdout, outbuf, outbufc);
|
|
outbufc = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
puts(char *s)
|
|
{
|
|
int count;
|
|
|
|
if (stdout == 0) {
|
|
putchar(*s++);
|
|
}
|
|
if (outbufc) {
|
|
OFWrite(stdout, outbuf, outbufc);
|
|
outbufc = 0;
|
|
}
|
|
if (count = strlen(s)) {
|
|
OFWrite(stdout, s, count);
|
|
}
|
|
putchar('\n');
|
|
}
|
|
|
|
STATIC ihandle stdin = 0;
|
|
|
|
VOID
|
|
gets(char *inbuf)
|
|
{
|
|
int count;
|
|
phandle ph;
|
|
|
|
if (stdin == 0) {
|
|
ph = OFFinddevice("/chosen");
|
|
if (ph == -1) {
|
|
/* What to do here?!? */
|
|
while (1) {
|
|
;
|
|
}
|
|
}
|
|
stdin = get_int_prop(ph, "stdin");
|
|
}
|
|
|
|
count = OFRead(stdin, inbuf, 127);
|
|
inbuf[count] = '\0';
|
|
}
|
|
|
|
#include <stdarg.h>
|
|
|
|
VOID
|
|
warn(char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
doprnt(putchar, fmt, args);
|
|
va_end(args);
|
|
}
|
|
|
|
VOID
|
|
fatal(char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
doprnt(putchar, fmt, args);
|
|
OFExit();
|
|
va_end(args);
|
|
}
|
|
|
|
int level = 0;
|
|
|
|
VOID
|
|
debug(int debug_level, char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
int i;
|
|
|
|
if (!(debug_level & VrDebug)) {
|
|
return;
|
|
}
|
|
va_start(args, fmt);
|
|
for (i = 0; i < level; ++i) {
|
|
putchar('\t');
|
|
}
|
|
doprnt(putchar, fmt, args);
|
|
va_end(args);
|
|
}
|
|
|
|
STATIC char *sprintf_buf;
|
|
|
|
STATIC VOID
|
|
putbuf(char c)
|
|
{
|
|
*sprintf_buf++ = c;
|
|
}
|
|
|
|
VOID
|
|
sprintf(char *buf, char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
sprintf_buf = buf;
|
|
va_start(args, fmt);
|
|
doprnt(putbuf, fmt, args);
|
|
va_end(args);
|
|
putbuf('\0');
|
|
}
|
|
|
|
STATIC VOID
|
|
doprnt(VOID (*func)(), char *fmt, va_list args)
|
|
{
|
|
ULONG x;
|
|
LONG l;
|
|
char c, *s;
|
|
|
|
while (c = *fmt++) {
|
|
if (c != '%') {
|
|
func(c);
|
|
continue;
|
|
}
|
|
switch (c = *fmt++) {
|
|
case 'x':
|
|
x = va_arg(args, ULONG);
|
|
printbase(func, x, 16);
|
|
break;
|
|
case 'o':
|
|
x = va_arg(args, ULONG);
|
|
printbase(func, x, 8);
|
|
break;
|
|
case 'd':
|
|
l = va_arg(args, LONG);
|
|
if (l < 0) {
|
|
func('-');
|
|
l = -l;
|
|
}
|
|
printbase(func, (ULONG) l, 10);
|
|
break;
|
|
case 'c':
|
|
c = va_arg(args, char);
|
|
func(c);
|
|
break;
|
|
case 's':
|
|
s = va_arg(args, char *);
|
|
while (*s) {
|
|
func(*s++);
|
|
}
|
|
break;
|
|
default:
|
|
func(c);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
STATIC VOID
|
|
printbase(VOID (*func)(), ULONG x, int base)
|
|
{
|
|
static char itoa[] = "0123456789abcdef";
|
|
ULONG j;
|
|
char buf[16], *s = buf;
|
|
|
|
if (x == 0) {
|
|
func('0');
|
|
return;
|
|
}
|
|
bzero(buf, 16);
|
|
while (x) {
|
|
j = x % base;
|
|
*s++ = itoa[j];
|
|
x -= j;
|
|
x /= base;
|
|
}
|
|
|
|
for (--s; s >= buf; --s) {
|
|
func(*s);
|
|
}
|
|
}
|