NetBSD/sys/arch/alpha/stand/standtest/test.c

508 lines
12 KiB
C

/* $NetBSD: test.c,v 1.3 2002/06/08 16:51:38 yamt Exp $ */
/*
* Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christopher G. Demetriou
* for the NetBSD Project.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
*/
#include <lib/libsa/stand.h>
#include <lib/libkern/libkern.h>
#include <machine/autoconf.h>
#include <machine/rpb.h>
#include "../common/common.h"
struct cmdtab {
const char *cmd;
void (*fn)(const char *buf);
};
int done;
unsigned long arg_pfn, arg_ptb, arg_bim, arg_bip, arg_biv;
const char *advance_past_space(const char *buf);
const char *cvt_number(const char *buf, u_int64_t *nump);
int dispatch_cmd(const char *buf, const struct cmdtab *cmds);
#define DISPATCH_CMD_NOCMD 0
#define DISPATCH_CMD_MATCHED 1
#define DISPATCH_CMD_NOMATCH 2
#define DISPATCH_CMD_AMBIGUOUS 3
void print_cmds(const struct cmdtab *cmds, const char *match,
size_t matchlen);
void print_stringarray(const char *s, size_t maxlen);
void toplevel_dpb(const char *buf);
void toplevel_dpl(const char *buf);
void toplevel_dpq(const char *buf);
void toplevel_dpw(const char *buf);
void toplevel_dvb(const char *buf);
void toplevel_dvl(const char *buf);
void toplevel_dvq(const char *buf);
void toplevel_dvw(const char *buf);
void toplevel_halt(const char *buf);
void toplevel_help(const char *buf);
void toplevel_show(const char *buf);
void show_args(const char *buf);
void show_bootinfo(const char *buf);
void show_pt(const char *buf);
void show_rpb(const char *buf);
void
main(pfn, ptb, bim, bip, biv)
unsigned long pfn; /* first free PFN number */
unsigned long ptb; /* PFN of current level 1 page table */
unsigned long bim; /* bootinfo magic */
unsigned long bip; /* bootinfo pointer */
unsigned long biv; /* bootinfo version */
{
char input_buf[512];
static const struct cmdtab toplevel_cmds[] = {
{ "?", toplevel_help, },
#if 0 /* XXX notyet */
{ "dpb", toplevel_dpb, },
{ "dpl", toplevel_dpl, },
{ "dpq", toplevel_dpq, },
{ "dpw", toplevel_dpw, },
{ "dvb", toplevel_dvb, },
{ "dvl", toplevel_dvl, },
{ "dvq", toplevel_dvq, },
{ "dvw", toplevel_dvw, },
#endif
{ "quit", toplevel_halt, },
{ "show", toplevel_show, },
{ NULL, },
};
printf("\n");
printf("NetBSD/alpha " NETBSD_VERS
" Standalone Test Program, Revision %s\n", bootprog_rev);
printf("(%s, %s)\n", bootprog_maker, bootprog_date);
printf("\n");
arg_pfn = pfn;
arg_ptb = ptb;
arg_bim = bim;
arg_bip = bip;
arg_biv = biv;
printf("Enter '?' for help.\n");
printf("\n");
do {
printf("test> ");
gets(input_buf);
dispatch_cmd(input_buf, toplevel_cmds);
} while (!done);
printf("\n");
printf("halting...\n");
halt();
}
const char *
advance_past_space(const char *buf)
{
/* advance past white space. */
while (isspace(*buf))
buf++;
if (*buf == '\0')
return NULL;
return buf;
}
const char *
cvt_number(const char *buf, u_int64_t *nump)
{
int base;
unsigned char c;
base = 10;
*nump = 0;
c = *buf;
if (c == '0') {
c = *(++buf);
if (c == 'x' || c == 'X') {
base = 16;
buf++;
} else {
base = 8;
}
}
for (c = *buf; c != '\0' && !isspace(c); c = *(++buf)) {
switch (base) {
case 10:
if (c < '0' || c > '9')
goto done;
}
}
done:
}
int
dispatch_cmd(const char *buf, const struct cmdtab *cmds)
{
const struct cmdtab *try, *winner;
size_t nonwhitespace, i;
unsigned int nmatches;
const char *pre, *post;
int rv;
/* advance past white space. */
buf = advance_past_space(buf);
if (buf == NULL)
return (DISPATCH_CMD_NOCMD);
/* find how much non-white space there is. */
nonwhitespace = 0;
while ((buf[nonwhitespace] != '\0') && !isspace(buf[nonwhitespace]))
nonwhitespace++;
/* at this point, nonwhitespace should always be non-zero */
if (nonwhitespace == 0) {
printf("assertion failed: dispatch_cmd: nonwhitespace == 0\n");
halt();
}
/* see how many matches there were. */
for (nmatches = 0, try = cmds;
try != NULL && try->cmd != NULL;
try++) {
if (strncmp(buf, try->cmd, nonwhitespace) == 0) {
winner = try;
nmatches++;
}
}
if (nmatches == 1) {
(*winner->fn)(buf + nonwhitespace);
return (DISPATCH_CMD_MATCHED);
} else if (nmatches == 0) {
pre = "invalid command word";
post = "allowed words";
rv = DISPATCH_CMD_NOMATCH;
} else {
pre = "ambiguous command word";
post = "matches";
rv = DISPATCH_CMD_AMBIGUOUS;
}
printf("%s \"", pre);
print_stringarray(buf, nonwhitespace);
printf("\", %s:\n", post);
/* print commands. if no match, print all commands. */
print_cmds(cmds, buf, rv == DISPATCH_CMD_NOMATCH ? 0 : nonwhitespace);
return (rv);
}
void
print_cmds(const struct cmdtab *cmds, const char *match, size_t matchlen)
{
const struct cmdtab *try;
printf(" ");
for (try = cmds; try != NULL && try->cmd != NULL; try++) {
if (strncmp(match, try->cmd, matchlen) == 0)
printf("%s%s", try != cmds ? ", " : "", try->cmd);
}
printf("\n");
}
void
print_stringarray(const char *s, size_t maxlen)
{
size_t i;
for (i = 0; (i < maxlen) && (*s != '\0'); i++, s++)
putchar(*s);
}
void
warn_ignored_args(const char *buf, const char *cmd)
{
if (advance_past_space(buf) != NULL)
printf("WARNING: extra arguments to \"%s\" command ignored\n",
cmd);
}
/*
* Top-level Commands
*/
void
toplevel_dpb(const char *buf)
{
u_int64_t startaddr, count = 1;
buf = advance_past_space(buf);
if (buf == NULL) {
printf("\"dpb\" must be given starting address\n");
return;
}
buf = cvt_number(buf, &startaddr);
if (*buf != '\0' && !isspace(*buf)) {
printf("bad character '%c' in starting address\n");
return;
}
buf = advance_past_space(buf);
if (buf != NULL) {
buf = cvt_number(buf, &count);
if (*buf != '\0' && !isspace(*buf)) {
printf("bad character '%c' in count\n");
return;
}
buf = advance_past_space(buf);
if (buf != NULL) {
printf("extra args at end of \"dpb\" command\n");
return;
}
}
printf("startaddr = 0x%lx, count = 0x%lx\n", startaddr, count);
printf("\"dpb\" not yet implemented\n");
}
void
toplevel_dpl(const char *buf)
{
printf("\"dpl\" not yet implemented\n");
}
void
toplevel_dpq(const char *buf)
{
printf("\"dpq\" not yet implemented\n");
}
void
toplevel_dpw(const char *buf)
{
printf("\"dpw\" not yet implemented\n");
}
void
toplevel_dvb(const char *buf)
{
printf("\"dvb\" not yet implemented\n");
}
void
toplevel_dvl(const char *buf)
{
printf("\"dvl\" not yet implemented\n");
}
void
toplevel_dvq(const char *buf)
{
printf("\"dvq\" not yet implemented\n");
}
void
toplevel_dvw(const char *buf)
{
printf("\"dvw\" not yet implemented\n");
}
void
toplevel_halt(const char *buf)
{
warn_ignored_args(buf, "halt");
done = 1;
}
void
toplevel_help(const char *buf)
{
warn_ignored_args(buf, "?");
printf("Standalone Test Program Commands:\n");
printf(" ? print help\n");
printf(" quit return to console\n");
#if 0 /* XXX notyet */
printf(" dpb startaddr [count] display physical memory "
"(8-bit units)\n");
printf(" dpw startaddr [count] display physical memory "
"(16-bit units)\n");
printf(" dpl startaddr [count] display physical memory "
"(32-bit units)\n");
printf(" dpq startaddr [count] display physical memory "
"(64-bit units)\n");
printf(" dvb startaddr [count] display virtual memory "
"(8-bit units)\n");
printf(" dvw startaddr [count] display virtual memory "
"(16-bit units)\n");
printf(" dvl startaddr [count] display virtual memory "
"(32-bit units)\n");
printf(" dvq startaddr [count] display virtual memory "
"(64-bit units)\n");
#endif
printf(" show args show test program arguments\n");
printf(" show bootinfo show bootstrap bootinfo\n");
#if 0 /* XXX notyet */
printf(" show pt [startaddr [endaddr]]\n");
printf(" show page tables\n");
printf(" show rpb show the HWRPB\n");
printf("\n");
printf("If optional \"count\" argument is omitted, 1 is used.\n");
printf("If optional \"startaddr\" argument is omitted, "
"0x0 is used.\n");
printf("If optional \"endaddr\" argument is omitted, "
"0xffffffffffffffff is used.\n");
#endif
}
void
toplevel_show(const char *buf)
{
static const struct cmdtab show_cmds[] = {
{ "args", show_args, },
{ "bootinfo", show_bootinfo, },
#if 0 /* XXX notyet */
{ "pt", show_pt, },
{ "rpb", show_rpb, },
#endif
{ NULL, },
};
if (dispatch_cmd(buf, show_cmds) == DISPATCH_CMD_NOCMD) {
printf("no subcommand given. allowed subcommands:\n");
print_cmds(show_cmds, NULL, 0);
}
}
/*
* Show Commands
*/
void
show_args(const char *buf)
{
warn_ignored_args(buf, "show args");
printf("first free page frame number: 0x%lx\n", arg_pfn);
printf("page table base page frame number: 0x%lx\n", arg_ptb);
printf("bootinfo magic number: 0x%lx\n", arg_bim);
printf("bootinfo pointer: 0x%lx\n", arg_bip);
printf("bootinfo version: 0x%lx\n", arg_biv);
}
void
show_bootinfo(const char *buf)
{
u_long biv, bip;
warn_ignored_args(buf, "show bootinfo");
if (arg_bim != BOOTINFO_MAGIC) {
printf("bootinfo magic number not present; no bootinfo\n");
return;
}
bip = arg_bip;
biv = arg_biv;
if (biv == 0) {
biv = *(u_long *)bip;
bip += 8;
}
printf("bootinfo version: %d\n", biv);
printf("bootinfo pointer: %p\n", (void *)bip);
printf("bootinfo data:\n");
switch (biv) {
case 1: {
const struct bootinfo_v1 *v1p;
int i;
v1p = (const struct bootinfo_v1 *)bip;
printf(" ssym: 0x%lx\n", v1p->ssym);
printf(" esym: 0x%lx\n", v1p->esym);
printf(" boot flags: \"");
print_stringarray(v1p->boot_flags, sizeof v1p->boot_flags);
printf("\"\n");
printf(" booted kernel: \"", v1p->esym);
print_stringarray(v1p->booted_kernel,
sizeof v1p->booted_kernel);
printf("\"\n");
printf(" hwrpb: %p\n", v1p->hwrpb);
printf(" hwrpbsize: 0x%lx\n", v1p->hwrpbsize);
printf(" cngetc: %p\n", v1p->cngetc);
printf(" cnputc: %p\n", v1p->cnputc);
printf(" cnpollc: %p\n", v1p->cnpollc);
for (i = 0; i < (sizeof v1p->pad / sizeof v1p->pad[0]); i++) {
printf(" pad[%d]: 0x%lx\n", i, v1p->pad[i]);
}
break;
}
default:
printf(" unknown bootinfo version, cannot print data\n");
break;
}
}
void
show_pt(const char *buf)
{
/* has additional args! */
printf("\"show pt\" not yet implemented\n");
}
void
show_rpb(const char *buf)
{
warn_ignored_args(buf, "show pt");
printf("\"show rpb\" not yet implemented\n");
}