test.c revision 1.2
1/* $NetBSD: test.c,v 1.2 1999/05/11 00:04:52 cgd 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
40struct cmdtab {
41	const char *cmd;
42	void (*fn)(const char *buf);
43};
44
45int		done;
46unsigned long	arg_pfn, arg_ptb, arg_bim, arg_bip, arg_biv;
47
48const char *advance_past_space(const char *buf);
49const char *cvt_number(const char *buf, u_int64_t *nump);
50int	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
55void	print_cmds(const struct cmdtab *cmds, const char *match,
56	    size_t matchlen);
57void	print_stringarray(const char *s, size_t maxlen);
58
59void	toplevel_dpb(const char *buf);
60void	toplevel_dpl(const char *buf);
61void	toplevel_dpq(const char *buf);
62void	toplevel_dpw(const char *buf);
63void	toplevel_dvb(const char *buf);
64void	toplevel_dvl(const char *buf);
65void	toplevel_dvq(const char *buf);
66void	toplevel_dvw(const char *buf);
67void	toplevel_halt(const char *buf);
68void	toplevel_help(const char *buf);
69void	toplevel_show(const char *buf);
70
71void	show_args(const char *buf);
72void	show_bootinfo(const char *buf);
73void	show_pt(const char *buf);
74void	show_rpb(const char *buf);
75
76void
77main(pfn, ptb, bim, bip, biv)
78	unsigned long pfn;	/* first free PFN number */
79	unsigned long ptb;	/* PFN of current level 1 page table */
80	unsigned long bim;	/* bootinfo magic */
81	unsigned long bip;	/* bootinfo pointer */
82	unsigned long biv;	/* bootinfo version */
83{
84	char input_buf[512];
85	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("(%s, %s)\n", bootprog_maker, bootprog_date);
106	printf("\n");
107
108	arg_pfn = pfn;
109	arg_ptb = ptb;
110	arg_bim = bim;
111	arg_bip = bip;
112	arg_biv = biv;
113
114	printf("Enter '?' for help.\n");
115	printf("\n");
116
117	do {
118		printf("test> ");
119		gets(input_buf);
120
121		dispatch_cmd(input_buf, toplevel_cmds);
122	} while (!done);
123
124	printf("\n");
125	printf("halting...\n");
126	halt();
127}
128
129const char *
130advance_past_space(const char *buf)
131{
132
133	/* advance past white space. */
134	while (isspace(*buf))
135		buf++;
136
137	if (*buf == '\0')
138		return NULL;
139	return buf;
140}
141
142const char *
143cvt_number(const char *buf, u_int64_t *nump)
144{
145	int base;
146	unsigned char c;
147
148	base = 10;
149	*nump = 0;
150
151	c = *buf;
152	if (c == '0') {
153		c = *(++buf);
154
155		if (c == 'x' || c == 'X') {
156			base = 16;
157			buf++;
158		} else {
159			base = 8;
160		}
161	}
162
163	for (c = *buf; c != '\0' && !isspace(c); c = *(++buf)) {
164		switch (base) {
165		case 10:
166			if (c < '0' || c > '9')
167				goto done;
168		}
169	}
170done:
171
172}
173
174int
175dispatch_cmd(const char *buf, const struct cmdtab *cmds)
176{
177	const struct cmdtab *try, *winner;
178	size_t nonwhitespace, i;
179	unsigned int nmatches;
180	const char *pre, *post;
181	int rv;
182
183	/* advance past white space. */
184	buf = advance_past_space(buf);
185	if (buf == NULL)
186		return (DISPATCH_CMD_NOCMD);
187
188	/* find how much non-white space there is. */
189	nonwhitespace = 0;
190	while ((buf[nonwhitespace] != '\0') && !isspace(buf[nonwhitespace]))
191		nonwhitespace++;
192
193	/* at this point, nonwhitespace should always be non-zero */
194	if (nonwhitespace == 0) {
195		printf("assertion failed: dispatch_cmd: nonwhitespace == 0\n");
196		halt();
197	}
198
199	/* see how many matches there were. */
200	for (nmatches = 0, try = cmds;
201	    try != NULL && try->cmd != NULL;
202	    try++) {
203		if (strncmp(buf, try->cmd, nonwhitespace) == 0) {
204			winner = try;
205			nmatches++;
206		}
207	}
208
209	if (nmatches == 1) {
210		(*winner->fn)(buf + nonwhitespace);
211		return (DISPATCH_CMD_MATCHED);
212	} else if (nmatches == 0) {
213		pre = "invalid command word";
214		post = "allowed words";
215		rv = DISPATCH_CMD_NOMATCH;
216	} else {
217		pre = "ambiguous command word";
218		post = "matches";
219		rv = DISPATCH_CMD_AMBIGUOUS;
220	}
221
222	printf("%s \"", pre);
223	print_stringarray(buf, nonwhitespace);
224	printf("\", %s:\n", post);
225
226	/* print commands.  if no match, print all commands. */
227	print_cmds(cmds, buf, rv == DISPATCH_CMD_NOMATCH ? 0 : nonwhitespace);
228	return (rv);
229}
230
231void
232print_cmds(const struct cmdtab *cmds, const char *match, size_t matchlen)
233{
234	const struct cmdtab *try;
235
236	printf("    ");
237	for (try = cmds; try != NULL && try->cmd != NULL; try++) {
238		if (strncmp(match, try->cmd, matchlen) == 0)
239			printf("%s%s", try != cmds ? ", " : "", try->cmd);
240	}
241	printf("\n");
242}
243
244void
245print_stringarray(const char *s, size_t maxlen)
246{
247	size_t i;
248
249	for (i = 0; (i < maxlen) && (*s != '\0'); i++, s++)
250		putchar(*s);
251}
252
253void
254warn_ignored_args(const char *buf, const char *cmd)
255{
256
257	if (advance_past_space(buf) != NULL)
258		printf("WARNING: extra arguments to \"%s\" command ignored\n",
259		    cmd);
260}
261
262
263/*
264 * Top-level Commands
265 */
266
267void
268toplevel_dpb(const char *buf)
269{
270	u_int64_t startaddr, count = 1;
271
272	buf = advance_past_space(buf);
273	if (buf == NULL) {
274		printf("\"dpb\" must be given starting address\n");
275		return;
276	}
277	buf = cvt_number(buf, &startaddr);
278	if (*buf != '\0' && !isspace(*buf)) {
279		printf("bad character '%c' in starting address\n");
280		return;
281	}
282
283	buf = advance_past_space(buf);
284	if (buf != NULL) {
285		buf = cvt_number(buf, &count);
286		if (*buf != '\0' && !isspace(*buf)) {
287			printf("bad character '%c' in count\n");
288			return;
289		}
290		buf = advance_past_space(buf);
291		if (buf != NULL) {
292			printf("extra args at end of \"dpb\" command\n");
293			return;
294		}
295	}
296
297	printf("startaddr = 0x%lx, count = 0x%lx\n", startaddr, count);
298	printf("\"dpb\" not yet implemented\n");
299}
300
301void
302toplevel_dpl(const char *buf)
303{
304
305	printf("\"dpl\" not yet implemented\n");
306}
307
308void
309toplevel_dpq(const char *buf)
310{
311
312	printf("\"dpq\" not yet implemented\n");
313}
314
315void
316toplevel_dpw(const char *buf)
317{
318
319	printf("\"dpw\" not yet implemented\n");
320}
321
322void
323toplevel_dvb(const char *buf)
324{
325
326	printf("\"dvb\" not yet implemented\n");
327}
328
329void
330toplevel_dvl(const char *buf)
331{
332
333	printf("\"dvl\" not yet implemented\n");
334}
335
336void
337toplevel_dvq(const char *buf)
338{
339
340	printf("\"dvq\" not yet implemented\n");
341}
342
343void
344toplevel_dvw(const char *buf)
345{
346
347	printf("\"dvw\" not yet implemented\n");
348}
349
350void
351toplevel_halt(const char *buf)
352{
353
354	warn_ignored_args(buf, "halt");
355
356	done = 1;
357}
358
359void
360toplevel_help(const char *buf)
361{
362
363	warn_ignored_args(buf, "?");
364
365	printf("Standalone Test Program Commands:\n");
366	printf("    ?                       print help\n");
367	printf("    quit                    return to console\n");
368#if 0 /* XXX notyet */
369	printf("    dpb startaddr [count]   display physical memory "
370	    "(8-bit units)\n");
371	printf("    dpw startaddr [count]   display physical memory "
372	    "(16-bit units)\n");
373	printf("    dpl startaddr [count]   display physical memory "
374	    "(32-bit units)\n");
375	printf("    dpq startaddr [count]   display physical memory "
376	    "(64-bit units)\n");
377	printf("    dvb startaddr [count]   display virtual memory "
378	    "(8-bit units)\n");
379	printf("    dvw startaddr [count]   display virtual memory "
380	    "(16-bit units)\n");
381	printf("    dvl startaddr [count]   display virtual memory "
382	    "(32-bit units)\n");
383	printf("    dvq startaddr [count]   display virtual memory "
384	    "(64-bit units)\n");
385#endif
386	printf("    show args               show test program arguments\n");
387	printf("    show bootinfo           show bootstrap bootinfo\n");
388#if 0 /* XXX notyet */
389	printf("    show pt [startaddr [endaddr]]\n");
390	printf("                            show page tables\n");
391	printf("    show rpb                show the HWRPB\n");
392	printf("\n");
393	printf("If optional \"count\" argument is omitted, 1 is used.\n");
394	printf("If optional \"startaddr\" argument is omitted, "
395	    "0x0 is used.\n");
396	printf("If optional \"endaddr\" argument is omitted, "
397	    "0xffffffffffffffff is used.\n");
398#endif
399}
400
401void
402toplevel_show(const char *buf)
403{
404	const struct cmdtab show_cmds[] = {
405	    {	"args",		show_args,	},
406	    {	"bootinfo",	show_bootinfo,	},
407#if 0 /* XXX notyet */
408	    {	"pt",		show_pt,	},
409	    {	"rpb",		show_rpb,	},
410#endif
411	    {	NULL,				},
412	};
413
414	if (dispatch_cmd(buf, show_cmds) == DISPATCH_CMD_NOCMD) {
415		printf("no subcommand given.  allowed subcommands:\n");
416		print_cmds(show_cmds, NULL, 0);
417	}
418}
419
420
421/*
422 * Show Commands
423 */
424
425void
426show_args(const char *buf)
427{
428
429	warn_ignored_args(buf, "show args");
430
431	printf("first free page frame number:       0x%lx\n", arg_pfn);
432	printf("page table base page frame number:  0x%lx\n", arg_ptb);
433	printf("bootinfo magic number:              0x%lx\n", arg_bim);
434	printf("bootinfo pointer:                   0x%lx\n", arg_bip);
435	printf("bootinfo version:                   0x%lx\n", arg_biv);
436}
437
438void
439show_bootinfo(const char *buf)
440{
441	u_long biv, bip;
442
443	warn_ignored_args(buf, "show bootinfo");
444
445	if (arg_bim != BOOTINFO_MAGIC) {
446		printf("bootinfo magic number not present; no bootinfo\n");
447		return;
448	}
449
450	bip = arg_bip;
451	biv = arg_biv;
452	if (biv == 0) {
453		biv = *(u_long *)bip;
454		bip += 8;
455	}
456
457	printf("bootinfo version: %d\n", biv);
458	printf("bootinfo pointer: %p\n", (void *)bip);
459	printf("bootinfo data:\n");
460
461	switch (biv) {
462	case 1: {
463		const struct bootinfo_v1 *v1p;
464		int i;
465
466		v1p = (const struct bootinfo_v1 *)bip;
467		printf("    ssym:          0x%lx\n", v1p->ssym);
468		printf("    esym:          0x%lx\n", v1p->esym);
469		printf("    boot flags:    \"");
470		print_stringarray(v1p->boot_flags, sizeof v1p->boot_flags);
471		printf("\"\n");
472		printf("    booted kernel: \"", v1p->esym);
473		print_stringarray(v1p->booted_kernel,
474		    sizeof v1p->booted_kernel);
475		printf("\"\n");
476		printf("    hwrpb:         %p\n", v1p->hwrpb);
477		printf("    hwrpbsize:     0x%lx\n", v1p->hwrpbsize);
478		printf("    cngetc:        %p\n", v1p->cngetc);
479		printf("    cnputc:        %p\n", v1p->cnputc);
480		printf("    cnpollc:       %p\n", v1p->cnpollc);
481		for (i = 0; i < (sizeof v1p->pad / sizeof v1p->pad[0]); i++) {
482			printf("    pad[%d]:        0x%lx\n", i, v1p->pad[i]);
483		}
484		break;
485	}
486	default:
487		printf("    unknown bootinfo version, cannot print data\n");
488		break;
489	}
490}
491
492void
493show_pt(const char *buf)
494{
495
496	/* has additional args! */
497	printf("\"show pt\" not yet implemented\n");
498}
499
500void
501show_rpb(const char *buf)
502{
503
504	warn_ignored_args(buf, "show pt");
505
506	printf("\"show rpb\" not yet implemented\n");
507}
508