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
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(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
128const char *
129advance_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
141const char *
142cvt_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	}
169done:
170
171}
172
173int
174dispatch_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
230void
231print_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
243void
244print_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
252void
253warn_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
266void
267toplevel_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
300void
301toplevel_dpl(const char *buf)
302{
303
304	printf("\"dpl\" not yet implemented\n");
305}
306
307void
308toplevel_dpq(const char *buf)
309{
310
311	printf("\"dpq\" not yet implemented\n");
312}
313
314void
315toplevel_dpw(const char *buf)
316{
317
318	printf("\"dpw\" not yet implemented\n");
319}
320
321void
322toplevel_dvb(const char *buf)
323{
324
325	printf("\"dvb\" not yet implemented\n");
326}
327
328void
329toplevel_dvl(const char *buf)
330{
331
332	printf("\"dvl\" not yet implemented\n");
333}
334
335void
336toplevel_dvq(const char *buf)
337{
338
339	printf("\"dvq\" not yet implemented\n");
340}
341
342void
343toplevel_dvw(const char *buf)
344{
345
346	printf("\"dvw\" not yet implemented\n");
347}
348
349void
350toplevel_halt(const char *buf)
351{
352
353	warn_ignored_args(buf, "halt");
354
355	done = 1;
356}
357
358void
359toplevel_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
400void
401toplevel_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
424void
425show_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
437void
438show_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
491void
492show_pt(const char *buf)
493{
494
495	/* has additional args! */
496	printf("\"show pt\" not yet implemented\n");
497}
498
499void
500show_rpb(const char *buf)
501{
502
503	warn_ignored_args(buf, "show pt");
504
505	printf("\"show rpb\" not yet implemented\n");
506}
507