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