main.c revision 1.5 1 /* $NetBSD: main.c,v 1.5 1997/07/23 20:58:40 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/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.5 1997/07/23 20:58:40 thorpej 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 bzero(errbuf, 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, *cp;
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 /*
267 * The whole point of the Openprom is that one
268 * isn't required to know the keywords. With this
269 * in mind, we just dump the whole thing off to
270 * the generic op_handler.
271 */
272 if ((cp = op_handler(keyword, arg)) != NULL)
273 warnx(cp);
274 return;
275 } else
276 #endif /* __sparc__ */
277 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent) {
278 if (strcmp(ktent->kt_keyword, keyword) == 0) {
279 (*ktent->kt_handler)(ktent, arg);
280 return;
281 }
282 }
283
284 warnx("unknown keyword %s", keyword);
285 ++eval;
286 }
287
288 /*
289 * Dump the contents of the prom corresponding to all known keywords.
290 */
291 static void
292 dump_prom()
293 {
294 struct keytabent *ktent;
295
296 #ifdef __sparc__
297 if (use_openprom) {
298 /*
299 * We have a special dump routine for this.
300 */
301 op_dump();
302 } else
303 #endif /* __sparc__ */
304 for (ktent = eekeytab; ktent->kt_keyword != NULL; ++ktent)
305 (*ktent->kt_handler)(ktent, NULL);
306 }
307
308 static void
309 usage()
310 {
311
312 #ifdef __sparc__
313 fprintf(stderr, "usage: %s %s %s\n", __progname,
314 "[-] [-c] [-f device] [-i] [-v]",
315 "[-N system] [field[=value] ...]");
316 #else
317 fprintf(stderr, "usage: %s %s\n", __progname,
318 "[-] [-c] [-f device] [-i] [field[=value] ...]");
319 #endif /* __sparc__ */
320 exit(1);
321 }
322