/* $NetBSD: test.c,v 1.7 2016/06/11 06:26:50 dholland 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 #include #include #include #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(unsigned long pfn, unsigned long ptb, unsigned long bim, unsigned long bip, unsigned long biv) /* pfn: first free PFN number */ /* ptb: PFN of current level 1 page table */ /* bim: bootinfo magic */ /* bip: bootinfo pointer */ /* 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("\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> "); kgets(input_buf, sizeof(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", *buf); 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", *buf); 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"); }