1 /* $NetBSD: main.c,v 1.3 1996/05/16 16:00:55 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1996 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE 30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <err.h> 41 #include <string.h> 42 #include <stdio.h> 43 #include <unistd.h> 44 45 #ifdef __sparc__ 46 #include <fcntl.h> 47 #include <kvm.h> 48 #include <limits.h> 49 #include <nlist.h> 50 51 #include <machine/openpromio.h> 52 53 struct nlist nl[] = { 54 { "_cputyp" }, 55 #define SYM_CPUTYP 0 56 { NULL }, 57 }; 58 59 static char *system = NULL; 60 #endif /* __sparc__ */ 61 62 #include <machine/eeprom.h> 63 64 #include "defs.h" 65 66 struct keytabent eekeytab[] = { 67 { "hwupdate", 0x10, ee_hwupdate }, 68 { "memsize", 0x14, ee_num8 }, 69 { "memtest", 0x15, ee_num8 }, 70 { "scrsize", 0x16, ee_screensize }, 71 { "watchdog_reboot", 0x17, ee_truefalse }, 72 { "default_boot", 0x18, ee_truefalse }, 73 { "bootdev", 0x19, ee_bootdev }, 74 { "kbdtype", 0x1e, ee_kbdtype }, 75 { "console", 0x1f, ee_constype }, 76 { "keyclick", 0x21, ee_truefalse }, 77 { "diagdev", 0x22, ee_bootdev }, 78 { "diagpath", 0x28, ee_diagpath }, 79 { "columns", 0x50, ee_num8 }, 80 { "rows", 0x51, ee_num8 }, 81 { "ttya_use_baud", 0x58, ee_truefalse }, 82 { "ttya_baud", 0x59, ee_num16 }, 83 { "ttya_no_rtsdtr", 0x5b, ee_truefalse }, 84 { "ttyb_use_baud", 0x60, ee_truefalse }, 85 { "ttyb_baud", 0x61, ee_num16 }, 86 { "ttyb_no_rtsdtr", 0x63, ee_truefalse }, 87 { "banner", 0x68, ee_banner }, 88 { "secure", 0, ee_notsupp }, 89 { "bad_login", 0, ee_notsupp }, 90 { "password", 0, ee_notsupp }, 91 { NULL, 0, ee_notsupp }, 92 }; 93 94 static void action __P((char *)); 95 static void dump_prom __P((void)); 96 static void usage __P((void)); 97 #ifdef __sparc__ 98 static int getcputype __P((void)); 99 #endif /* __sparc__ */ 100 101 char *path_eeprom = "/dev/eeprom"; 102 char *path_openprom = "/dev/openprom"; 103 int fix_checksum = 0; 104 int ignore_checksum = 0; 105 int update_checksums = 0; 106 int cksumfail = 0; 107 u_short writecount; 108 int eval = 0; 109 int use_openprom = 0; 110 int verbose = 0; 111 112 extern char *__progname; 113 114 int 115 main(argc, argv) 116 int argc; 117 char **argv; 118 { 119 int ch, do_stdin = 0; 120 char *cp, line[BUFSIZE]; 121 #ifdef __sparc__ 122 char *optstring = "-cf:ivN:"; 123 #else 124 char *optstring = "-cf:i"; 125 #endif /* __sparc__ */ 126 127 while ((ch = getopt(argc, argv, optstring)) != -1) 128 switch (ch) { 129 case '-': 130 do_stdin = 1; 131 break; 132 133 case 'c': 134 fix_checksum = 1; 135 break; 136 137 case 'f': 138 path_eeprom = path_openprom = optarg; 139 break; 140 141 case 'i': 142 ignore_checksum = 1; 143 break; 144 #ifdef __sparc__ 145 case 'v': 146 verbose = 1; 147 break; 148 149 case 'N': 150 system = optarg; 151 break; 152 153 #endif /* __sparc__ */ 154 155 case '?': 156 default: 157 usage(); 158 } 159 argc -= optind; 160 argv += optind; 161 162 #ifdef __sparc__ 163 if (getcputype() != CPU_SUN4) 164 use_openprom = 1; 165 #endif /* __sparc__ */ 166 167 if (use_openprom == 0) { 168 ee_verifychecksums(); 169 if (fix_checksum || cksumfail) 170 exit(cksumfail); 171 } 172 173 if (do_stdin) { 174 while (fgets(line, BUFSIZE, stdin) != NULL) { 175 if (line[0] == '\n') 176 continue; 177 if ((cp = strrchr(line, '\n')) != NULL) 178 *cp = '\0'; 179 action(line); 180 } 181 if (ferror(stdin)) 182 err(++eval, "stdin"); 183 } else { 184 if (argc == 0) { 185 dump_prom(); 186 exit(eval + cksumfail); 187 } 188 189 while (argc) { 190 action(*argv); 191 ++argv; 192 --argc; 193 } 194 } 195 196 if (use_openprom == 0) 197 if (update_checksums) { 198 ++writecount; 199 ee_updatechecksums(); 200 } 201 202 exit(eval + cksumfail); 203 } 204 205 #ifdef __sparc__ 206 #define KVM_ABORT(kd, str) { \ 207 (void)kvm_close((kd)); \ 208 errx(1, "%s: %s", (str), kvm_geterr((kd))); \ 209 } 210 211 static int 212 getcputype() 213 { 214 char errbuf[_POSIX2_LINE_MAX]; 215 int cputype; 216 kvm_t *kd; 217 218 bzero(errbuf, sizeof(errbuf)); 219 220 if ((kd = kvm_openfiles(system, NULL, NULL, O_RDONLY, errbuf)) == NULL) 221 errx(1, "can't open kvm: %s", errbuf); 222 223 if (kvm_nlist(kd, nl)) 224 KVM_ABORT(kd, "can't read symbol table"); 225 226 if (kvm_read(kd, nl[SYM_CPUTYP].n_value, (char *)&cputype, 227 sizeof(cputype)) != sizeof(cputype)) 228 KVM_ABORT(kd, "can't determine cpu type"); 229 230 (void)kvm_close(kd); 231 return (cputype); 232 } 233 #endif /* __sparc__ */ 234 235 /* 236 * Separate the keyword from the argument (if any), find the keyword in 237 * the table, and call the corresponding handler function. 238 */ 239 static void 240 action(line) 241 char *line; 242 { 243 char *keyword, *arg, *cp; 244 struct keytabent *ktent; 245 246 keyword = strdup(line); 247 if ((arg = strrchr(keyword, '=')) != NULL) 248 *arg++ = '\0'; 249 250 #ifdef __sparc__ 251 if (use_openprom) { 252 /* 253 * The whole point of the Openprom is that one 254 * isn't required to know the keywords. With this 255 * in mind, we just dump the whole thing off to 256 * the generic op_handler. 257 */ 258 if ((cp = op_handler(keyword, arg)) != NULL) 259 warnx(cp); 260 return; 261 } else 262 #endif /* __sparc__ */ 263 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) { 264 if (strcmp(ktent->kt_keyword, keyword) == 0) { 265 (*ktent->kt_handler)(ktent, arg); 266 return; 267 } 268 } 269 270 warnx("unknown keyword %s", keyword); 271 ++eval; 272 } 273 274 /* 275 * Dump the contents of the prom corresponding to all known keywords. 276 */ 277 static void 278 dump_prom() 279 { 280 struct keytabent *ktent; 281 282 #ifdef __sparc__ 283 if (use_openprom) { 284 /* 285 * We have a special dump routine for this. 286 */ 287 op_dump(); 288 } else 289 #endif /* __sparc__ */ 290 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) 291 (*ktent->kt_handler)(ktent, NULL); 292 } 293 294 static void 295 usage() 296 { 297 298 #ifdef __sparc__ 299 fprintf(stderr, "usage: %s %s %s\n", __progname, 300 "[-] [-c] [-f device] [-i] [-v]", 301 "[-N system] [field[=value] ...]"); 302 #else 303 fprintf(stderr, "usage: %s %s\n", __progname, 304 "[-] [-c] [-f device] [-i] [field[=value] ...]"); 305 #endif /* __sparc__ */ 306 exit(1); 307 } 308