Home | History | Annotate | Line # | Download | only in standtest
      1 /* $NetBSD: test.c,v 1.7 2016/06/11 06:26:50 dholland Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1999 Christopher G. Demetriou.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Christopher G. Demetriou
     17  *	for the NetBSD Project.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <lib/libsa/stand.h>
     34 #include <lib/libkern/libkern.h>
     35 #include <machine/autoconf.h>
     36 #include <machine/rpb.h>
     37 
     38 #include "../common/common.h"
     39 
     40 struct cmdtab {
     41 	const char *cmd;
     42 	void (*fn)(const char *buf);
     43 };
     44 
     45 int		done;
     46 unsigned long	arg_pfn, arg_ptb, arg_bim, arg_bip, arg_biv;
     47 
     48 const char *advance_past_space(const char *buf);
     49 const char *cvt_number(const char *buf, u_int64_t *nump);
     50 int	dispatch_cmd(const char *buf, const struct cmdtab *cmds);
     51 #define		DISPATCH_CMD_NOCMD	0
     52 #define		DISPATCH_CMD_MATCHED	1
     53 #define		DISPATCH_CMD_NOMATCH	2
     54 #define		DISPATCH_CMD_AMBIGUOUS	3
     55 void	print_cmds(const struct cmdtab *cmds, const char *match,
     56 	    size_t matchlen);
     57 void	print_stringarray(const char *s, size_t maxlen);
     58 
     59 void	toplevel_dpb(const char *buf);
     60 void	toplevel_dpl(const char *buf);
     61 void	toplevel_dpq(const char *buf);
     62 void	toplevel_dpw(const char *buf);
     63 void	toplevel_dvb(const char *buf);
     64 void	toplevel_dvl(const char *buf);
     65 void	toplevel_dvq(const char *buf);
     66 void	toplevel_dvw(const char *buf);
     67 void	toplevel_halt(const char *buf);
     68 void	toplevel_help(const char *buf);
     69 void	toplevel_show(const char *buf);
     70 
     71 void	show_args(const char *buf);
     72 void	show_bootinfo(const char *buf);
     73 void	show_pt(const char *buf);
     74 void	show_rpb(const char *buf);
     75 
     76 void
     77 main(unsigned long pfn, unsigned long ptb, unsigned long bim, unsigned long bip, unsigned long biv)
     78 	/* pfn:	 first free PFN number */
     79 	/* ptb:	 PFN of current level 1 page table */
     80 	/* bim:	 bootinfo magic */
     81 	/* bip:	 bootinfo pointer */
     82 	/* biv:	 bootinfo version */
     83 {
     84 	char input_buf[512];
     85 	static const struct cmdtab toplevel_cmds[] = {
     86 	    {	"?",		toplevel_help,	},
     87 #if 0 /* XXX notyet */
     88 	    {	"dpb",		toplevel_dpb,	},
     89 	    {	"dpl",		toplevel_dpl,	},
     90 	    {	"dpq",		toplevel_dpq,	},
     91 	    {	"dpw",		toplevel_dpw,	},
     92 	    {	"dvb",		toplevel_dvb,	},
     93 	    {	"dvl",		toplevel_dvl,	},
     94 	    {	"dvq",		toplevel_dvq,	},
     95 	    {	"dvw",		toplevel_dvw,	},
     96 #endif
     97 	    {	"quit",		toplevel_halt,	},
     98 	    {	"show",		toplevel_show,	},
     99 	    {	NULL,				},
    100 	};
    101 
    102 	printf("\n");
    103 	printf("NetBSD/alpha " NETBSD_VERS
    104 	    " Standalone Test Program, Revision %s\n", bootprog_rev);
    105 	printf("\n");
    106 
    107 	arg_pfn = pfn;
    108 	arg_ptb = ptb;
    109 	arg_bim = bim;
    110 	arg_bip = bip;
    111 	arg_biv = biv;
    112 
    113 	printf("Enter '?' for help.\n");
    114 	printf("\n");
    115 
    116 	do {
    117 		printf("test> ");
    118 		kgets(input_buf, sizeof(input_buf));
    119 
    120 		dispatch_cmd(input_buf, toplevel_cmds);
    121 	} while (!done);
    122 
    123 	printf("\n");
    124 	printf("halting...\n");
    125 	halt();
    126 }
    127 
    128 const char *
    129 advance_past_space(const char *buf)
    130 {
    131 
    132 	/* advance past white space. */
    133 	while (isspace(*buf))
    134 		buf++;
    135 
    136 	if (*buf == '\0')
    137 		return NULL;
    138 	return buf;
    139 }
    140 
    141 const char *
    142 cvt_number(const char *buf, u_int64_t *nump)
    143 {
    144 	int base;
    145 	unsigned char c;
    146 
    147 	base = 10;
    148 	*nump = 0;
    149 
    150 	c = *buf;
    151 	if (c == '0') {
    152 		c = *(++buf);
    153 
    154 		if (c == 'x' || c == 'X') {
    155 			base = 16;
    156 			buf++;
    157 		} else {
    158 			base = 8;
    159 		}
    160 	}
    161 
    162 	for (c = *buf; c != '\0' && !isspace(c); c = *(++buf)) {
    163 		switch (base) {
    164 		case 10:
    165 			if (c < '0' || c > '9')
    166 				goto done;
    167 		}
    168 	}
    169 done:
    170 
    171 }
    172 
    173 int
    174 dispatch_cmd(const char *buf, const struct cmdtab *cmds)
    175 {
    176 	const struct cmdtab *try, *winner;
    177 	size_t nonwhitespace, i;
    178 	unsigned int nmatches;
    179 	const char *pre, *post;
    180 	int rv;
    181 
    182 	/* advance past white space. */
    183 	buf = advance_past_space(buf);
    184 	if (buf == NULL)
    185 		return (DISPATCH_CMD_NOCMD);
    186 
    187 	/* find how much non-white space there is. */
    188 	nonwhitespace = 0;
    189 	while ((buf[nonwhitespace] != '\0') && !isspace(buf[nonwhitespace]))
    190 		nonwhitespace++;
    191 
    192 	/* at this point, nonwhitespace should always be non-zero */
    193 	if (nonwhitespace == 0) {
    194 		printf("assertion failed: dispatch_cmd: nonwhitespace == 0\n");
    195 		halt();
    196 	}
    197 
    198 	/* see how many matches there were. */
    199 	for (nmatches = 0, try = cmds;
    200 	    try != NULL && try->cmd != NULL;
    201 	    try++) {
    202 		if (strncmp(buf, try->cmd, nonwhitespace) == 0) {
    203 			winner = try;
    204 			nmatches++;
    205 		}
    206 	}
    207 
    208 	if (nmatches == 1) {
    209 		(*winner->fn)(buf + nonwhitespace);
    210 		return (DISPATCH_CMD_MATCHED);
    211 	} else if (nmatches == 0) {
    212 		pre = "invalid command word";
    213 		post = "allowed words";
    214 		rv = DISPATCH_CMD_NOMATCH;
    215 	} else {
    216 		pre = "ambiguous command word";
    217 		post = "matches";
    218 		rv = DISPATCH_CMD_AMBIGUOUS;
    219 	}
    220 
    221 	printf("%s \"", pre);
    222 	print_stringarray(buf, nonwhitespace);
    223 	printf("\", %s:\n", post);
    224 
    225 	/* print commands.  if no match, print all commands. */
    226 	print_cmds(cmds, buf, rv == DISPATCH_CMD_NOMATCH ? 0 : nonwhitespace);
    227 	return (rv);
    228 }
    229 
    230 void
    231 print_cmds(const struct cmdtab *cmds, const char *match, size_t matchlen)
    232 {
    233 	const struct cmdtab *try;
    234 
    235 	printf("    ");
    236 	for (try = cmds; try != NULL && try->cmd != NULL; try++) {
    237 		if (strncmp(match, try->cmd, matchlen) == 0)
    238 			printf("%s%s", try != cmds ? ", " : "", try->cmd);
    239 	}
    240 	printf("\n");
    241 }
    242 
    243 void
    244 print_stringarray(const char *s, size_t maxlen)
    245 {
    246 	size_t i;
    247 
    248 	for (i = 0; (i < maxlen) && (*s != '\0'); i++, s++)
    249 		putchar(*s);
    250 }
    251 
    252 void
    253 warn_ignored_args(const char *buf, const char *cmd)
    254 {
    255 
    256 	if (advance_past_space(buf) != NULL)
    257 		printf("WARNING: extra arguments to \"%s\" command ignored\n",
    258 		    cmd);
    259 }
    260 
    261 
    262 /*
    263  * Top-level Commands
    264  */
    265 
    266 void
    267 toplevel_dpb(const char *buf)
    268 {
    269 	u_int64_t startaddr, count = 1;
    270 
    271 	buf = advance_past_space(buf);
    272 	if (buf == NULL) {
    273 		printf("\"dpb\" must be given starting address\n");
    274 		return;
    275 	}
    276 	buf = cvt_number(buf, &startaddr);
    277 	if (*buf != '\0' && !isspace(*buf)) {
    278 		printf("bad character '%c' in starting address\n", *buf);
    279 		return;
    280 	}
    281 
    282 	buf = advance_past_space(buf);
    283 	if (buf != NULL) {
    284 		buf = cvt_number(buf, &count);
    285 		if (*buf != '\0' && !isspace(*buf)) {
    286 			printf("bad character '%c' in count\n", *buf);
    287 			return;
    288 		}
    289 		buf = advance_past_space(buf);
    290 		if (buf != NULL) {
    291 			printf("extra args at end of \"dpb\" command\n");
    292 			return;
    293 		}
    294 	}
    295 
    296 	printf("startaddr = 0x%lx, count = 0x%lx\n", startaddr, count);
    297 	printf("\"dpb\" not yet implemented\n");
    298 }
    299 
    300 void
    301 toplevel_dpl(const char *buf)
    302 {
    303 
    304 	printf("\"dpl\" not yet implemented\n");
    305 }
    306 
    307 void
    308 toplevel_dpq(const char *buf)
    309 {
    310 
    311 	printf("\"dpq\" not yet implemented\n");
    312 }
    313 
    314 void
    315 toplevel_dpw(const char *buf)
    316 {
    317 
    318 	printf("\"dpw\" not yet implemented\n");
    319 }
    320 
    321 void
    322 toplevel_dvb(const char *buf)
    323 {
    324 
    325 	printf("\"dvb\" not yet implemented\n");
    326 }
    327 
    328 void
    329 toplevel_dvl(const char *buf)
    330 {
    331 
    332 	printf("\"dvl\" not yet implemented\n");
    333 }
    334 
    335 void
    336 toplevel_dvq(const char *buf)
    337 {
    338 
    339 	printf("\"dvq\" not yet implemented\n");
    340 }
    341 
    342 void
    343 toplevel_dvw(const char *buf)
    344 {
    345 
    346 	printf("\"dvw\" not yet implemented\n");
    347 }
    348 
    349 void
    350 toplevel_halt(const char *buf)
    351 {
    352 
    353 	warn_ignored_args(buf, "halt");
    354 
    355 	done = 1;
    356 }
    357 
    358 void
    359 toplevel_help(const char *buf)
    360 {
    361 
    362 	warn_ignored_args(buf, "?");
    363 
    364 	printf("Standalone Test Program Commands:\n");
    365 	printf("    ?                       print help\n");
    366 	printf("    quit                    return to console\n");
    367 #if 0 /* XXX notyet */
    368 	printf("    dpb startaddr [count]   display physical memory "
    369 	    "(8-bit units)\n");
    370 	printf("    dpw startaddr [count]   display physical memory "
    371 	    "(16-bit units)\n");
    372 	printf("    dpl startaddr [count]   display physical memory "
    373 	    "(32-bit units)\n");
    374 	printf("    dpq startaddr [count]   display physical memory "
    375 	    "(64-bit units)\n");
    376 	printf("    dvb startaddr [count]   display virtual memory "
    377 	    "(8-bit units)\n");
    378 	printf("    dvw startaddr [count]   display virtual memory "
    379 	    "(16-bit units)\n");
    380 	printf("    dvl startaddr [count]   display virtual memory "
    381 	    "(32-bit units)\n");
    382 	printf("    dvq startaddr [count]   display virtual memory "
    383 	    "(64-bit units)\n");
    384 #endif
    385 	printf("    show args               show test program arguments\n");
    386 	printf("    show bootinfo           show bootstrap bootinfo\n");
    387 #if 0 /* XXX notyet */
    388 	printf("    show pt [startaddr [endaddr]]\n");
    389 	printf("                            show page tables\n");
    390 	printf("    show rpb                show the HWRPB\n");
    391 	printf("\n");
    392 	printf("If optional \"count\" argument is omitted, 1 is used.\n");
    393 	printf("If optional \"startaddr\" argument is omitted, "
    394 	    "0x0 is used.\n");
    395 	printf("If optional \"endaddr\" argument is omitted, "
    396 	    "0xffffffffffffffff is used.\n");
    397 #endif
    398 }
    399 
    400 void
    401 toplevel_show(const char *buf)
    402 {
    403 	static const struct cmdtab show_cmds[] = {
    404 	    {	"args",		show_args,	},
    405 	    {	"bootinfo",	show_bootinfo,	},
    406 #if 0 /* XXX notyet */
    407 	    {	"pt",		show_pt,	},
    408 	    {	"rpb",		show_rpb,	},
    409 #endif
    410 	    {	NULL,				},
    411 	};
    412 
    413 	if (dispatch_cmd(buf, show_cmds) == DISPATCH_CMD_NOCMD) {
    414 		printf("no subcommand given.  allowed subcommands:\n");
    415 		print_cmds(show_cmds, NULL, 0);
    416 	}
    417 }
    418 
    419 
    420 /*
    421  * Show Commands
    422  */
    423 
    424 void
    425 show_args(const char *buf)
    426 {
    427 
    428 	warn_ignored_args(buf, "show args");
    429 
    430 	printf("first free page frame number:       0x%lx\n", arg_pfn);
    431 	printf("page table base page frame number:  0x%lx\n", arg_ptb);
    432 	printf("bootinfo magic number:              0x%lx\n", arg_bim);
    433 	printf("bootinfo pointer:                   0x%lx\n", arg_bip);
    434 	printf("bootinfo version:                   0x%lx\n", arg_biv);
    435 }
    436 
    437 void
    438 show_bootinfo(const char *buf)
    439 {
    440 	u_long biv, bip;
    441 
    442 	warn_ignored_args(buf, "show bootinfo");
    443 
    444 	if (arg_bim != BOOTINFO_MAGIC) {
    445 		printf("bootinfo magic number not present; no bootinfo\n");
    446 		return;
    447 	}
    448 
    449 	bip = arg_bip;
    450 	biv = arg_biv;
    451 	if (biv == 0) {
    452 		biv = *(u_long *)bip;
    453 		bip += 8;
    454 	}
    455 
    456 	printf("bootinfo version: %d\n", biv);
    457 	printf("bootinfo pointer: %p\n", (void *)bip);
    458 	printf("bootinfo data:\n");
    459 
    460 	switch (biv) {
    461 	case 1: {
    462 		const struct bootinfo_v1 *v1p;
    463 		int i;
    464 
    465 		v1p = (const struct bootinfo_v1 *)bip;
    466 		printf("    ssym:          0x%lx\n", v1p->ssym);
    467 		printf("    esym:          0x%lx\n", v1p->esym);
    468 		printf("    boot flags:    \"");
    469 		print_stringarray(v1p->boot_flags, sizeof v1p->boot_flags);
    470 		printf("\"\n");
    471 		printf("    booted kernel: \"", v1p->esym);
    472 		print_stringarray(v1p->booted_kernel,
    473 		    sizeof v1p->booted_kernel);
    474 		printf("\"\n");
    475 		printf("    hwrpb:         %p\n", v1p->hwrpb);
    476 		printf("    hwrpbsize:     0x%lx\n", v1p->hwrpbsize);
    477 		printf("    cngetc:        %p\n", v1p->cngetc);
    478 		printf("    cnputc:        %p\n", v1p->cnputc);
    479 		printf("    cnpollc:       %p\n", v1p->cnpollc);
    480 		for (i = 0; i < (sizeof v1p->pad / sizeof v1p->pad[0]); i++) {
    481 			printf("    pad[%d]:        0x%lx\n", i, v1p->pad[i]);
    482 		}
    483 		break;
    484 	}
    485 	default:
    486 		printf("    unknown bootinfo version, cannot print data\n");
    487 		break;
    488 	}
    489 }
    490 
    491 void
    492 show_pt(const char *buf)
    493 {
    494 
    495 	/* has additional args! */
    496 	printf("\"show pt\" not yet implemented\n");
    497 }
    498 
    499 void
    500 show_rpb(const char *buf)
    501 {
    502 
    503 	warn_ignored_args(buf, "show pt");
    504 
    505 	printf("\"show rpb\" not yet implemented\n");
    506 }
    507