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