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
main(unsigned long pfn,unsigned long ptb,unsigned long bim,unsigned long bip,unsigned long biv)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 *
advance_past_space(const char * buf)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 *
cvt_number(const char * buf,u_int64_t * nump)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
dispatch_cmd(const char * buf,const struct cmdtab * cmds)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
print_cmds(const struct cmdtab * cmds,const char * match,size_t matchlen)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
print_stringarray(const char * s,size_t maxlen)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
warn_ignored_args(const char * buf,const char * cmd)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
toplevel_dpb(const char * buf)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
toplevel_dpl(const char * buf)301 toplevel_dpl(const char *buf)
302 {
303
304 printf("\"dpl\" not yet implemented\n");
305 }
306
307 void
toplevel_dpq(const char * buf)308 toplevel_dpq(const char *buf)
309 {
310
311 printf("\"dpq\" not yet implemented\n");
312 }
313
314 void
toplevel_dpw(const char * buf)315 toplevel_dpw(const char *buf)
316 {
317
318 printf("\"dpw\" not yet implemented\n");
319 }
320
321 void
toplevel_dvb(const char * buf)322 toplevel_dvb(const char *buf)
323 {
324
325 printf("\"dvb\" not yet implemented\n");
326 }
327
328 void
toplevel_dvl(const char * buf)329 toplevel_dvl(const char *buf)
330 {
331
332 printf("\"dvl\" not yet implemented\n");
333 }
334
335 void
toplevel_dvq(const char * buf)336 toplevel_dvq(const char *buf)
337 {
338
339 printf("\"dvq\" not yet implemented\n");
340 }
341
342 void
toplevel_dvw(const char * buf)343 toplevel_dvw(const char *buf)
344 {
345
346 printf("\"dvw\" not yet implemented\n");
347 }
348
349 void
toplevel_halt(const char * buf)350 toplevel_halt(const char *buf)
351 {
352
353 warn_ignored_args(buf, "halt");
354
355 done = 1;
356 }
357
358 void
toplevel_help(const char * buf)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
toplevel_show(const char * buf)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
show_args(const char * buf)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
show_bootinfo(const char * buf)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
show_pt(const char * buf)492 show_pt(const char *buf)
493 {
494
495 /* has additional args! */
496 printf("\"show pt\" not yet implemented\n");
497 }
498
499 void
show_rpb(const char * buf)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