1 /* $NetBSD: main.c,v 1.4 1996/09/27 02:39:46 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 /* 164 * Discard setgid setgid privileges if not the running kernel so 165 * that bad guys can't print interesting stuff from kernel memory. 166 */ 167 if (system != NULL) 168 setgid(getgid()); 169 if (getcputype() != CPU_SUN4) 170 use_openprom = 1; 171 #endif /* __sparc__ */ 172 173 if (use_openprom == 0) { 174 ee_verifychecksums(); 175 if (fix_checksum || cksumfail) 176 exit(cksumfail); 177 } 178 179 if (do_stdin) { 180 while (fgets(line, BUFSIZE, stdin) != NULL) { 181 if (line[0] == '\n') 182 continue; 183 if ((cp = strrchr(line, '\n')) != NULL) 184 *cp = '\0'; 185 action(line); 186 } 187 if (ferror(stdin)) 188 err(++eval, "stdin"); 189 } else { 190 if (argc == 0) { 191 dump_prom(); 192 exit(eval + cksumfail); 193 } 194 195 while (argc) { 196 action(*argv); 197 ++argv; 198 --argc; 199 } 200 } 201 202 if (use_openprom == 0) 203 if (update_checksums) { 204 ++writecount; 205 ee_updatechecksums(); 206 } 207 208 exit(eval + cksumfail); 209 } 210 211 #ifdef __sparc__ 212 #define KVM_ABORT(kd, str) { \ 213 (void)kvm_close((kd)); \ 214 errx(1, "%s: %s", (str), kvm_geterr((kd))); \ 215 } 216 217 static int 218 getcputype() 219 { 220 char errbuf[_POSIX2_LINE_MAX]; 221 int cputype; 222 kvm_t *kd; 223 224 bzero(errbuf, sizeof(errbuf)); 225 226 if ((kd = kvm_openfiles(system, NULL, NULL, O_RDONLY, errbuf)) == NULL) 227 errx(1, "can't open kvm: %s", errbuf); 228 229 if (kvm_nlist(kd, nl)) 230 KVM_ABORT(kd, "can't read symbol table"); 231 232 if (kvm_read(kd, nl[SYM_CPUTYP].n_value, (char *)&cputype, 233 sizeof(cputype)) != sizeof(cputype)) 234 KVM_ABORT(kd, "can't determine cpu type"); 235 236 (void)kvm_close(kd); 237 return (cputype); 238 } 239 #endif /* __sparc__ */ 240 241 /* 242 * Separate the keyword from the argument (if any), find the keyword in 243 * the table, and call the corresponding handler function. 244 */ 245 static void 246 action(line) 247 char *line; 248 { 249 char *keyword, *arg, *cp; 250 struct keytabent *ktent; 251 252 keyword = strdup(line); 253 if ((arg = strrchr(keyword, '=')) != NULL) 254 *arg++ = '\0'; 255 256 #ifdef __sparc__ 257 if (use_openprom) { 258 /* 259 * The whole point of the Openprom is that one 260 * isn't required to know the keywords. With this 261 * in mind, we just dump the whole thing off to 262 * the generic op_handler. 263 */ 264 if ((cp = op_handler(keyword, arg)) != NULL) 265 warnx(cp); 266 return; 267 } else 268 #endif /* __sparc__ */ 269 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) { 270 if (strcmp(ktent->kt_keyword, keyword) == 0) { 271 (*ktent->kt_handler)(ktent, arg); 272 return; 273 } 274 } 275 276 warnx("unknown keyword %s", keyword); 277 ++eval; 278 } 279 280 /* 281 * Dump the contents of the prom corresponding to all known keywords. 282 */ 283 static void 284 dump_prom() 285 { 286 struct keytabent *ktent; 287 288 #ifdef __sparc__ 289 if (use_openprom) { 290 /* 291 * We have a special dump routine for this. 292 */ 293 op_dump(); 294 } else 295 #endif /* __sparc__ */ 296 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) 297 (*ktent->kt_handler)(ktent, NULL); 298 } 299 300 static void 301 usage() 302 { 303 304 #ifdef __sparc__ 305 fprintf(stderr, "usage: %s %s %s\n", __progname, 306 "[-] [-c] [-f device] [-i] [-v]", 307 "[-N system] [field[=value] ...]"); 308 #else 309 fprintf(stderr, "usage: %s %s\n", __progname, 310 "[-] [-c] [-f device] [-i] [field[=value] ...]"); 311 #endif /* __sparc__ */ 312 exit(1); 313 } 314