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