1 /* $NetBSD: main.c,v 1.8 1997/10/18 08:40:49 lukem 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 FOUNDATION OR CONTRIBUTORS 30 * BE 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/cdefs.h> 40 #ifndef lint 41 __COPYRIGHT( 42 "@(#) Copyright (c) 1996 The NetBSD Foundation, Inc. All rights reserved."); 43 __RCSID("$NetBSD: main.c,v 1.8 1997/10/18 08:40:49 lukem Exp $"); 44 #endif 45 46 #include <sys/param.h> 47 #include <err.h> 48 #include <string.h> 49 #include <stdio.h> 50 #include <unistd.h> 51 52 #ifdef __sparc__ 53 #include <fcntl.h> 54 #include <kvm.h> 55 #include <limits.h> 56 #include <nlist.h> 57 58 #include <machine/openpromio.h> 59 60 struct nlist nl[] = { 61 { "_cputyp" }, 62 #define SYM_CPUTYP 0 63 { NULL }, 64 }; 65 66 static char *system = NULL; 67 #endif /* __sparc__ */ 68 69 #include <machine/eeprom.h> 70 71 #include "defs.h" 72 73 struct keytabent eekeytab[] = { 74 { "hwupdate", 0x10, ee_hwupdate }, 75 { "memsize", 0x14, ee_num8 }, 76 { "memtest", 0x15, ee_num8 }, 77 { "scrsize", 0x16, ee_screensize }, 78 { "watchdog_reboot", 0x17, ee_truefalse }, 79 { "default_boot", 0x18, ee_truefalse }, 80 { "bootdev", 0x19, ee_bootdev }, 81 { "kbdtype", 0x1e, ee_kbdtype }, 82 { "console", 0x1f, ee_constype }, 83 { "keyclick", 0x21, ee_truefalse }, 84 { "diagdev", 0x22, ee_bootdev }, 85 { "diagpath", 0x28, ee_diagpath }, 86 { "columns", 0x50, ee_num8 }, 87 { "rows", 0x51, ee_num8 }, 88 { "ttya_use_baud", 0x58, ee_truefalse }, 89 { "ttya_baud", 0x59, ee_num16 }, 90 { "ttya_no_rtsdtr", 0x5b, ee_truefalse }, 91 { "ttyb_use_baud", 0x60, ee_truefalse }, 92 { "ttyb_baud", 0x61, ee_num16 }, 93 { "ttyb_no_rtsdtr", 0x63, ee_truefalse }, 94 { "banner", 0x68, ee_banner }, 95 { "secure", 0, ee_notsupp }, 96 { "bad_login", 0, ee_notsupp }, 97 { "password", 0, ee_notsupp }, 98 { NULL, 0, ee_notsupp }, 99 }; 100 101 int main __P((int, char *[])); 102 static void action __P((char *)); 103 static void dump_prom __P((void)); 104 static void usage __P((void)); 105 #ifdef __sparc__ 106 static int getcputype __P((void)); 107 #endif /* __sparc__ */ 108 109 char *path_eeprom = "/dev/eeprom"; 110 char *path_openprom = "/dev/openprom"; 111 int fix_checksum = 0; 112 int ignore_checksum = 0; 113 int update_checksums = 0; 114 int cksumfail = 0; 115 u_short writecount; 116 int eval = 0; 117 int use_openprom = 0; 118 int verbose = 0; 119 120 extern char *__progname; 121 122 int 123 main(argc, argv) 124 int argc; 125 char *argv[]; 126 { 127 int ch, do_stdin = 0; 128 char *cp, line[BUFSIZE]; 129 #ifdef __sparc__ 130 char *optstring = "-cf:ivN:"; 131 #else 132 char *optstring = "-cf:i"; 133 #endif /* __sparc__ */ 134 135 while ((ch = getopt(argc, argv, optstring)) != -1) 136 switch (ch) { 137 case '-': 138 do_stdin = 1; 139 break; 140 141 case 'c': 142 fix_checksum = 1; 143 break; 144 145 case 'f': 146 path_eeprom = path_openprom = optarg; 147 break; 148 149 case 'i': 150 ignore_checksum = 1; 151 break; 152 #ifdef __sparc__ 153 case 'v': 154 verbose = 1; 155 break; 156 157 case 'N': 158 system = optarg; 159 break; 160 161 #endif /* __sparc__ */ 162 163 case '?': 164 default: 165 usage(); 166 } 167 argc -= optind; 168 argv += optind; 169 170 #ifdef __sparc__ 171 /* 172 * Discard setgid setgid privileges if not the running kernel so 173 * that bad guys can't print interesting stuff from kernel memory. 174 */ 175 if (system != NULL) 176 setgid(getgid()); 177 if (getcputype() != CPU_SUN4) 178 use_openprom = 1; 179 #endif /* __sparc__ */ 180 181 if (use_openprom == 0) { 182 ee_verifychecksums(); 183 if (fix_checksum || cksumfail) 184 exit(cksumfail); 185 } 186 187 if (do_stdin) { 188 while (fgets(line, BUFSIZE, stdin) != NULL) { 189 if (line[0] == '\n') 190 continue; 191 if ((cp = strrchr(line, '\n')) != NULL) 192 *cp = '\0'; 193 action(line); 194 } 195 if (ferror(stdin)) 196 err(++eval, "stdin"); 197 } else { 198 if (argc == 0) { 199 dump_prom(); 200 exit(eval + cksumfail); 201 } 202 203 while (argc) { 204 action(*argv); 205 ++argv; 206 --argc; 207 } 208 } 209 210 if (use_openprom == 0) 211 if (update_checksums) { 212 ++writecount; 213 ee_updatechecksums(); 214 } 215 216 exit(eval + cksumfail); 217 } 218 219 #ifdef __sparc__ 220 #define KVM_ABORT(kd, str) { \ 221 (void)kvm_close((kd)); \ 222 errx(1, "%s: %s", (str), kvm_geterr((kd))); \ 223 } 224 225 static int 226 getcputype() 227 { 228 char errbuf[_POSIX2_LINE_MAX]; 229 int cputype; 230 kvm_t *kd; 231 232 memset(errbuf, 0, sizeof(errbuf)); 233 234 if ((kd = kvm_openfiles(system, NULL, NULL, O_RDONLY, errbuf)) == NULL) 235 errx(1, "can't open kvm: %s", errbuf); 236 237 if (kvm_nlist(kd, nl)) 238 KVM_ABORT(kd, "can't read symbol table"); 239 240 if (kvm_read(kd, nl[SYM_CPUTYP].n_value, (char *)&cputype, 241 sizeof(cputype)) != sizeof(cputype)) 242 KVM_ABORT(kd, "can't determine cpu type"); 243 244 (void)kvm_close(kd); 245 return (cputype); 246 } 247 #endif /* __sparc__ */ 248 249 /* 250 * Separate the keyword from the argument (if any), find the keyword in 251 * the table, and call the corresponding handler function. 252 */ 253 static void 254 action(line) 255 char *line; 256 { 257 char *keyword, *arg; 258 struct keytabent *ktent; 259 260 keyword = strdup(line); 261 if ((arg = strrchr(keyword, '=')) != NULL) 262 *arg++ = '\0'; 263 264 #ifdef __sparc__ 265 if (use_openprom) { 266 char *cp; 267 /* 268 * The whole point of the Openprom is that one 269 * isn't required to know the keywords. With this 270 * in mind, we just dump the whole thing off to 271 * the generic op_handler. 272 */ 273 if ((cp = op_handler(keyword, arg)) != NULL) 274 warnx(cp); 275 return; 276 } else 277 #endif /* __sparc__ */ 278 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) { 279 if (strcmp(ktent->kt_keyword, keyword) == 0) { 280 (*ktent->kt_handler)(ktent, arg); 281 return; 282 } 283 } 284 285 warnx("unknown keyword %s", keyword); 286 ++eval; 287 } 288 289 /* 290 * Dump the contents of the prom corresponding to all known keywords. 291 */ 292 static void 293 dump_prom() 294 { 295 struct keytabent *ktent; 296 297 #ifdef __sparc__ 298 if (use_openprom) { 299 /* 300 * We have a special dump routine for this. 301 */ 302 op_dump(); 303 } else 304 #endif /* __sparc__ */ 305 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) 306 (*ktent->kt_handler)(ktent, NULL); 307 } 308 309 static void 310 usage() 311 { 312 313 #ifdef __sparc__ 314 fprintf(stderr, "usage: %s %s %s\n", __progname, 315 "[-] [-c] [-f device] [-i] [-v]", 316 "[-N system] [field[=value] ...]"); 317 #else 318 fprintf(stderr, "usage: %s %s\n", __progname, 319 "[-] [-c] [-f device] [-i] [field[=value] ...]"); 320 #endif /* __sparc__ */ 321 exit(1); 322 } 323