1ae115bc7Smrj /*
2ae115bc7Smrj * Open Boot Prom eeprom utility
3*23a1cceaSRoger A. Faulkner */
4*23a1cceaSRoger A. Faulkner
5*23a1cceaSRoger A. Faulkner /*
6*23a1cceaSRoger A. Faulkner * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
7ae115bc7Smrj */
8ae115bc7Smrj
9ae115bc7Smrj /*
10ae115bc7Smrj * Copyright (c) 1983 Regents of the University of California.
11ae115bc7Smrj * All rights reserved. The Berkeley software License Agreement
12ae115bc7Smrj * specifies the terms and conditions for redistribution.
13ae115bc7Smrj */
14ae115bc7Smrj
15ae115bc7Smrj #include <sys/types.h>
16ae115bc7Smrj #include <sys/param.h>
17ae115bc7Smrj #include <sys/openpromio.h>
18ae115bc7Smrj #include <stdio.h>
19ae115bc7Smrj #include <fcntl.h>
20ae115bc7Smrj #include <string.h>
21ae115bc7Smrj #include <errno.h>
22ae115bc7Smrj #include <stdlib.h>
23ae115bc7Smrj #include <unistd.h>
24ae115bc7Smrj
25ae115bc7Smrj /*
26ae115bc7Smrj * Usage: % eeprom [-v] [-f promdev] [-]
27ae115bc7Smrj * % eeprom [-v] [-f promdev] field[=value] ...
28ae115bc7Smrj */
29ae115bc7Smrj
30ae115bc7Smrj /*
31ae115bc7Smrj * 128 is the size of the largest (currently) property name buffer
32ae115bc7Smrj * 8192 - MAXPROPSIZE - sizeof (int) is the size of the largest
33ae115bc7Smrj * (currently) property value, viz. nvramrc.
34ae115bc7Smrj * the sizeof(u_int) is from struct openpromio
35ae115bc7Smrj */
36ae115bc7Smrj
37ae115bc7Smrj #define MAXPROPSIZE 128
38ae115bc7Smrj #define MAXNAMESIZE MAXPROPSIZE
39ae115bc7Smrj #define MAXVALSIZE (8192 - MAXPROPSIZE - sizeof (uint_t))
40ae115bc7Smrj #define BUFSIZE (MAXPROPSIZE + MAXVALSIZE + sizeof (uint_t))
41ae115bc7Smrj typedef union {
42ae115bc7Smrj char buf[BUFSIZE];
43ae115bc7Smrj struct openpromio opp;
44ae115bc7Smrj } Oppbuf;
45ae115bc7Smrj
46ae115bc7Smrj extern int _error(int do_perror, char *fmt, ...);
47*23a1cceaSRoger A. Faulkner extern void setpname(char *);
48ae115bc7Smrj static int get_password(char *, int);
49ae115bc7Smrj extern int loadlogo(char *, int, int, char *);
50ae115bc7Smrj
51ae115bc7Smrj #define NO_PERROR 0
52ae115bc7Smrj #define PERROR 1
53ae115bc7Smrj
54ae115bc7Smrj static int prom_fd;
55ae115bc7Smrj static char *promdev;
56ae115bc7Smrj static int verbose;
57ae115bc7Smrj
58ae115bc7Smrj static void do_var(char *);
59ae115bc7Smrj static void dump_all();
60ae115bc7Smrj static void print_one(char *);
61ae115bc7Smrj static void set_one(char *, char *);
62ae115bc7Smrj static void promclose();
63ae115bc7Smrj static int promopen(int);
64ae115bc7Smrj
65ae115bc7Smrj static int getpropval(struct openpromio *);
66ae115bc7Smrj static int setpropval(struct openpromio *);
67ae115bc7Smrj
68ae115bc7Smrj static char *badarchmsg = "Architecture does not support this command.\n";
69ae115bc7Smrj
70ae115bc7Smrj typedef void (*func)();
71ae115bc7Smrj
72ae115bc7Smrj
73ae115bc7Smrj /* We have to special-case two properties related to security */
74ae115bc7Smrj static void i_secure();
75ae115bc7Smrj static void i_passwd(), o_passwd();
76ae115bc7Smrj static void i_oemlogo();
77ae115bc7Smrj
78ae115bc7Smrj /*
79ae115bc7Smrj * It's unfortunate that we have to know the names of certain properties
80ae115bc7Smrj * in this program (the whole idea of openprom was to avoid it), but at
81ae115bc7Smrj * least we can isolate them to these defines here.
82ae115bc7Smrj */
83ae115bc7Smrj #define PASSWORD_PROPERTY "security-password"
84ae115bc7Smrj #define MODE_PROPERTY "security-mode"
85ae115bc7Smrj #define LOGO_PROPERTY "oem-logo"
86ae115bc7Smrj #define PW_SIZE 8
87ae115bc7Smrj
88ae115bc7Smrj /*
89ae115bc7Smrj * Unlike the old-style eeprom command, where every property needed an
90ae115bc7Smrj * i_foo and an o_foo function, we only need them when the default case
91ae115bc7Smrj * isn't sufficient.
92ae115bc7Smrj */
93ae115bc7Smrj static struct opvar {
94ae115bc7Smrj char *name;
95ae115bc7Smrj func in;
96ae115bc7Smrj func out;
97ae115bc7Smrj } opvar[] = {
98ae115bc7Smrj #define e(n, i, o) {n, i, o}
99ae115bc7Smrj e(MODE_PROPERTY, i_secure, (func)NULL),
100ae115bc7Smrj e(PASSWORD_PROPERTY, i_passwd, o_passwd),
101ae115bc7Smrj e(LOGO_PROPERTY, i_oemlogo, (func)NULL),
102ae115bc7Smrj { (char *)NULL, (func)NULL, (func)NULL}
103ae115bc7Smrj #undef e
104ae115bc7Smrj };
105ae115bc7Smrj
106ae115bc7Smrj
107ae115bc7Smrj /*
108ae115bc7Smrj * sun4c openprom
109ae115bc7Smrj */
110ae115bc7Smrj
111ae115bc7Smrj int
main(int argc,char ** argv)112ae115bc7Smrj main(int argc, char **argv)
113ae115bc7Smrj {
114ae115bc7Smrj int c;
115ae115bc7Smrj extern char *optarg;
116ae115bc7Smrj extern int optind;
117ae115bc7Smrj
118ae115bc7Smrj promdev = "/dev/openprom";
119ae115bc7Smrj
120ae115bc7Smrj while ((c = getopt(argc, argv, "cif:v")) != -1)
121ae115bc7Smrj switch (c) {
122ae115bc7Smrj case 'c':
123ae115bc7Smrj case 'i':
124ae115bc7Smrj /* ignore for openprom */
125ae115bc7Smrj break;
126ae115bc7Smrj case 'v':
127ae115bc7Smrj verbose++;
128ae115bc7Smrj break;
129ae115bc7Smrj case 'f':
130ae115bc7Smrj promdev = optarg;
131ae115bc7Smrj break;
132ae115bc7Smrj default:
133ae115bc7Smrj exit(_error(NO_PERROR,
134ae115bc7Smrj "Usage: %s [-v] [-f prom-device] "
135ae115bc7Smrj "[variable[=value] ...]", argv[0]));
136ae115bc7Smrj }
137ae115bc7Smrj
138*23a1cceaSRoger A. Faulkner setpname(argv[0]);
139ae115bc7Smrj
140ae115bc7Smrj /*
141ae115bc7Smrj * If no arguments, dump all fields.
142ae115bc7Smrj */
143ae115bc7Smrj if (optind >= argc) {
144ae115bc7Smrj dump_all();
145ae115bc7Smrj exit(0);
146ae115bc7Smrj }
147ae115bc7Smrj
148ae115bc7Smrj while (optind < argc) {
149ae115bc7Smrj /*
150ae115bc7Smrj * If "-" specified, read variables from stdin.
151ae115bc7Smrj */
152ae115bc7Smrj if (strcmp(argv[optind], "-") == 0) {
153ae115bc7Smrj int c;
154ae115bc7Smrj char *nl, line[BUFSIZE];
155ae115bc7Smrj
156ae115bc7Smrj while (fgets(line, sizeof (line), stdin) != NULL) {
157ae115bc7Smrj /* zap newline if present */
158ae115bc7Smrj if (nl = strchr(line, '\n'))
159ae115bc7Smrj *nl = 0;
160ae115bc7Smrj /* otherwise discard rest of line */
161ae115bc7Smrj else
162ae115bc7Smrj while ((c = getchar()) != '\n' &&
163ae115bc7Smrj c != EOF)
164ae115bc7Smrj /* nothing */;
165ae115bc7Smrj
166ae115bc7Smrj do_var(line);
167ae115bc7Smrj }
168ae115bc7Smrj clearerr(stdin);
169ae115bc7Smrj }
170ae115bc7Smrj /*
171ae115bc7Smrj * Process each argument as a variable print or set request.
172ae115bc7Smrj */
173ae115bc7Smrj else
174ae115bc7Smrj do_var(argv[optind]);
175ae115bc7Smrj
176ae115bc7Smrj optind++;
177ae115bc7Smrj }
178ae115bc7Smrj return (0);
179ae115bc7Smrj }
180ae115bc7Smrj
181ae115bc7Smrj /*
182ae115bc7Smrj * Print or set an EEPROM field.
183ae115bc7Smrj */
184ae115bc7Smrj static void
do_var(char * var)185ae115bc7Smrj do_var(char *var)
186ae115bc7Smrj {
187ae115bc7Smrj char *val;
188ae115bc7Smrj
189ae115bc7Smrj val = strchr(var, '=');
190ae115bc7Smrj
191ae115bc7Smrj if (val == NULL) {
192ae115bc7Smrj /*
193ae115bc7Smrj * print specific property
194ae115bc7Smrj */
195ae115bc7Smrj if (promopen(O_RDONLY)) {
196ae115bc7Smrj (void) fprintf(stderr, badarchmsg);
197ae115bc7Smrj exit(1);
198ae115bc7Smrj }
199ae115bc7Smrj print_one(var);
200ae115bc7Smrj } else {
201ae115bc7Smrj /*
202ae115bc7Smrj * set specific property to value
203ae115bc7Smrj */
204ae115bc7Smrj *val++ = '\0';
205ae115bc7Smrj
206ae115bc7Smrj if (promopen(O_RDWR)) {
207ae115bc7Smrj (void) fprintf(stderr, badarchmsg);
208ae115bc7Smrj exit(1);
209ae115bc7Smrj }
210ae115bc7Smrj set_one(var, val);
211ae115bc7Smrj }
212ae115bc7Smrj promclose();
213ae115bc7Smrj }
214ae115bc7Smrj
215ae115bc7Smrj /*
216ae115bc7Smrj * Print all properties and values
217ae115bc7Smrj */
218ae115bc7Smrj static void
dump_all()219ae115bc7Smrj dump_all()
220ae115bc7Smrj {
221ae115bc7Smrj Oppbuf oppbuf;
222ae115bc7Smrj struct openpromio *opp = &(oppbuf.opp);
223ae115bc7Smrj
224ae115bc7Smrj if (promopen(O_RDONLY)) {
225ae115bc7Smrj (void) fprintf(stderr, badarchmsg);
226ae115bc7Smrj exit(1);
227ae115bc7Smrj }
228ae115bc7Smrj /* get first prop by asking for null string */
229ae115bc7Smrj (void) memset(oppbuf.buf, '\0', BUFSIZE);
230ae115bc7Smrj /* CONSTCOND */
231ae115bc7Smrj while (1) {
232ae115bc7Smrj /*
233ae115bc7Smrj * get property
234ae115bc7Smrj */
235ae115bc7Smrj opp->oprom_size = MAXPROPSIZE;
236ae115bc7Smrj
237ae115bc7Smrj if (ioctl(prom_fd, OPROMNXTOPT, opp) < 0)
238ae115bc7Smrj exit(_error(PERROR, "OPROMNXTOPT"));
239ae115bc7Smrj
240ae115bc7Smrj if (opp->oprom_size == 0) {
241ae115bc7Smrj promclose();
242ae115bc7Smrj return;
243ae115bc7Smrj }
244ae115bc7Smrj print_one(opp->oprom_array);
245ae115bc7Smrj }
246ae115bc7Smrj }
247ae115bc7Smrj
248ae115bc7Smrj /*
249ae115bc7Smrj * Print one property and its value.
250ae115bc7Smrj */
251ae115bc7Smrj static void
print_one(char * var)252ae115bc7Smrj print_one(char *var)
253ae115bc7Smrj {
254ae115bc7Smrj Oppbuf oppbuf;
255ae115bc7Smrj struct openpromio *opp = &(oppbuf.opp);
2563b133becSGangadhar Mylapuram char bootargs[MAXVALSIZE];
2573b133becSGangadhar Mylapuram
2583b133becSGangadhar Mylapuram if (strcmp(var, "bootcmd") == 0) {
2593b133becSGangadhar Mylapuram opp->oprom_size = MAXVALSIZE;
2603b133becSGangadhar Mylapuram if (ioctl(prom_fd, OPROMGETBOOTARGS, opp) < 0) {
2613b133becSGangadhar Mylapuram (void) _error(PERROR, "OPROMGETBOOTARGS");
2623b133becSGangadhar Mylapuram return;
2633b133becSGangadhar Mylapuram }
2643b133becSGangadhar Mylapuram (void) strlcpy(bootargs, opp->oprom_array, MAXVALSIZE);
2653b133becSGangadhar Mylapuram
2663b133becSGangadhar Mylapuram opp->oprom_size = MAXVALSIZE;
2673b133becSGangadhar Mylapuram if (ioctl(prom_fd, OPROMGETBOOTPATH, opp) < 0) {
2683b133becSGangadhar Mylapuram (void) _error(PERROR, "OPROMGETBOOTPATH");
2693b133becSGangadhar Mylapuram return;
2703b133becSGangadhar Mylapuram }
2713b133becSGangadhar Mylapuram (void) printf("%s=%s %s\n", var, opp->oprom_array, bootargs);
2723b133becSGangadhar Mylapuram return;
2733b133becSGangadhar Mylapuram }
274ae115bc7Smrj
275ae115bc7Smrj (void) strlcpy(opp->oprom_array, var, MAXNAMESIZE);
276ae115bc7Smrj if (getpropval(opp) || opp->oprom_size <= 0)
277ae115bc7Smrj (void) printf("%s: data not available.\n", var);
278ae115bc7Smrj else {
279ae115bc7Smrj /* If necessary, massage the output */
280ae115bc7Smrj struct opvar *v;
281ae115bc7Smrj
282ae115bc7Smrj for (v = opvar; v->name; v++)
283ae115bc7Smrj if (strcmp(var, v->name) == 0)
284ae115bc7Smrj break;
285ae115bc7Smrj
286ae115bc7Smrj if (v->name && v->out)
287ae115bc7Smrj (*v->out)(v->name, opp->oprom_array);
288ae115bc7Smrj else
289ae115bc7Smrj (void) printf("%s=%s\n", var, opp->oprom_array);
290ae115bc7Smrj }
291ae115bc7Smrj }
292ae115bc7Smrj
293ae115bc7Smrj /*
294ae115bc7Smrj * Set one property to the given value.
295ae115bc7Smrj */
296ae115bc7Smrj static void
set_one(char * var,char * val)297ae115bc7Smrj set_one(char *var, char *val)
298ae115bc7Smrj {
299ae115bc7Smrj Oppbuf oppbuf;
300ae115bc7Smrj struct openpromio *opp = &(oppbuf.opp);
301ae115bc7Smrj struct opvar *v;
302ae115bc7Smrj
303ae115bc7Smrj if (verbose) {
304ae115bc7Smrj (void) printf("old:");
305ae115bc7Smrj print_one(var);
306ae115bc7Smrj }
307ae115bc7Smrj
308ae115bc7Smrj /* If necessary, massage the input */
309ae115bc7Smrj
310ae115bc7Smrj for (v = opvar; v->name; v++)
311ae115bc7Smrj if (strcmp(var, v->name) == 0)
312ae115bc7Smrj break;
313ae115bc7Smrj
314ae115bc7Smrj if (v->name && v->in)
315ae115bc7Smrj (*v->in)(v->name, val, opp);
316ae115bc7Smrj else {
317ae115bc7Smrj int varlen = strlen(var) + 1;
318ae115bc7Smrj int vallen = strlen(val);
319ae115bc7Smrj
320ae115bc7Smrj if (varlen > MAXNAMESIZE) {
321ae115bc7Smrj (void) printf("%s: invalid property.\n", var);
322ae115bc7Smrj return;
323ae115bc7Smrj }
324ae115bc7Smrj if (vallen >= MAXVALSIZE) {
325ae115bc7Smrj (void) printf("%s: invalid property value.\n", var);
326ae115bc7Smrj return;
327ae115bc7Smrj }
328ae115bc7Smrj (void) strcpy(opp->oprom_array, var);
329ae115bc7Smrj (void) strcpy(opp->oprom_array + varlen, val);
330ae115bc7Smrj opp->oprom_size = varlen + vallen;
331ae115bc7Smrj if (setpropval(opp))
332ae115bc7Smrj (void) printf("%s: invalid property.\n", var);
333ae115bc7Smrj }
334ae115bc7Smrj
335ae115bc7Smrj if (verbose) {
336ae115bc7Smrj (void) printf("new:");
337ae115bc7Smrj print_one(var);
338ae115bc7Smrj }
339ae115bc7Smrj }
340ae115bc7Smrj
341ae115bc7Smrj static int
promopen(int oflag)342ae115bc7Smrj promopen(int oflag)
343ae115bc7Smrj {
344ae115bc7Smrj /* CONSTCOND */
345ae115bc7Smrj while (1) {
346ae115bc7Smrj if ((prom_fd = open(promdev, oflag)) < 0) {
347ae115bc7Smrj if (errno == EAGAIN)
348ae115bc7Smrj continue;
349ae115bc7Smrj else if (errno == ENXIO)
350ae115bc7Smrj return (-1);
351ae115bc7Smrj else
352ae115bc7Smrj exit(_error(PERROR, "cannot open %s", promdev));
353ae115bc7Smrj } else
354ae115bc7Smrj break;
355ae115bc7Smrj }
356ae115bc7Smrj return (0);
357ae115bc7Smrj }
358ae115bc7Smrj
359ae115bc7Smrj static void
promclose()360ae115bc7Smrj promclose()
361ae115bc7Smrj {
362ae115bc7Smrj if (close(prom_fd) < 0)
363ae115bc7Smrj exit(_error(PERROR, "close error on %s", promdev));
364ae115bc7Smrj }
365ae115bc7Smrj
366ae115bc7Smrj static int
getpropval(struct openpromio * opp)367ae115bc7Smrj getpropval(struct openpromio *opp)
368ae115bc7Smrj {
369ae115bc7Smrj opp->oprom_size = MAXVALSIZE;
370ae115bc7Smrj
371ae115bc7Smrj if (ioctl(prom_fd, OPROMGETOPT, opp) < 0)
372ae115bc7Smrj return (_error(PERROR, "OPROMGETOPT"));
373ae115bc7Smrj
374ae115bc7Smrj return (0);
375ae115bc7Smrj }
376ae115bc7Smrj
377ae115bc7Smrj static int
setpropval(struct openpromio * opp)378ae115bc7Smrj setpropval(struct openpromio *opp)
379ae115bc7Smrj {
380ae115bc7Smrj /* Caller must set opp->oprom_size */
381ae115bc7Smrj
382ae115bc7Smrj if (ioctl(prom_fd, OPROMSETOPT, opp) < 0)
383ae115bc7Smrj return (_error(PERROR, "OPROMSETOPT"));
384ae115bc7Smrj return (0);
385ae115bc7Smrj }
386ae115bc7Smrj
387ae115bc7Smrj
388ae115bc7Smrj /*
389ae115bc7Smrj * The next set of functions handle the special cases.
390ae115bc7Smrj */
391ae115bc7Smrj
392ae115bc7Smrj static void
i_oemlogo(char * var,char * val,struct openpromio * opp)393ae115bc7Smrj i_oemlogo(char *var, char *val, struct openpromio *opp)
394ae115bc7Smrj {
395ae115bc7Smrj int varlen = strlen(var) + 1;
396ae115bc7Smrj
397ae115bc7Smrj (void) strcpy(opp->oprom_array, var); /* safe - we know the name */
398ae115bc7Smrj
399ae115bc7Smrj if (loadlogo(val, 64, 64, opp->oprom_array + varlen))
400ae115bc7Smrj exit(1);
401ae115bc7Smrj opp->oprom_size = varlen + 512;
402ae115bc7Smrj if (ioctl(prom_fd, OPROMSETOPT2, opp) < 0)
403ae115bc7Smrj exit(_error(PERROR, "OPROMSETOPT2"));
404ae115bc7Smrj }
405ae115bc7Smrj
406ae115bc7Smrj /*
407ae115bc7Smrj * Set security mode.
408ae115bc7Smrj * If oldmode was none, and new mode is not none, get and set password,
409ae115bc7Smrj * too.
410ae115bc7Smrj * If old mode was not none, and new mode is none, wipe out old
411ae115bc7Smrj * password.
412ae115bc7Smrj */
413ae115bc7Smrj static void
i_secure(char * var,char * val,struct openpromio * opp)414ae115bc7Smrj i_secure(char *var, char *val, struct openpromio *opp)
415ae115bc7Smrj {
416ae115bc7Smrj int secure;
417ae115bc7Smrj Oppbuf oppbuf;
418ae115bc7Smrj struct openpromio *opp2 = &(oppbuf.opp);
419ae115bc7Smrj char pwbuf[PW_SIZE + 2];
420ae115bc7Smrj int varlen1, varlen2;
421ae115bc7Smrj
422ae115bc7Smrj (void) strcpy(opp2->oprom_array, var); /* safe; we know the name */
423ae115bc7Smrj if (getpropval(opp2) || opp2->oprom_size <= 0) {
424ae115bc7Smrj (void) printf("%s: data not available.\n", var);
425ae115bc7Smrj exit(1);
426ae115bc7Smrj }
427ae115bc7Smrj secure = strcmp(opp2->oprom_array, "none");
428ae115bc7Smrj
429ae115bc7Smrj /* Set up opp for mode */
430ae115bc7Smrj (void) strcpy(opp->oprom_array, var); /* safe; we know the name */
431ae115bc7Smrj varlen1 = strlen(opp->oprom_array) + 1;
432ae115bc7Smrj if (strlen(val) > 32) { /* 32 > [ "full", "command", "none" ] */
433ae115bc7Smrj (void) printf("Invalid security mode, mode unchanged.\n");
434ae115bc7Smrj exit(1);
435ae115bc7Smrj }
436ae115bc7Smrj (void) strcpy(opp->oprom_array + varlen1, val);
437ae115bc7Smrj opp->oprom_size = varlen1 + strlen(val);
438ae115bc7Smrj
439ae115bc7Smrj /* Set up opp2 for password */
440ae115bc7Smrj (void) strcpy(opp2->oprom_array, PASSWORD_PROPERTY);
441ae115bc7Smrj varlen2 = strlen(opp2->oprom_array) + 1;
442ae115bc7Smrj
443ae115bc7Smrj if ((strcmp(val, "full") == 0) || (strcmp(val, "command") == 0)) {
444ae115bc7Smrj if (! secure) {
445ae115bc7Smrj /* no password yet, get one */
446ae115bc7Smrj if (get_password(pwbuf, PW_SIZE)) {
447ae115bc7Smrj (void) strcpy(opp2->oprom_array + varlen2,
448ae115bc7Smrj pwbuf);
449ae115bc7Smrj opp2->oprom_size = varlen2 + strlen(pwbuf);
450ae115bc7Smrj /* set password first */
451ae115bc7Smrj if (setpropval(opp2) || setpropval(opp))
452ae115bc7Smrj exit(1);
453ae115bc7Smrj } else
454ae115bc7Smrj exit(1);
455ae115bc7Smrj } else {
456ae115bc7Smrj if (setpropval(opp))
457ae115bc7Smrj exit(1);
458ae115bc7Smrj }
459ae115bc7Smrj } else if (strcmp(val, "none") == 0) {
460ae115bc7Smrj if (secure) {
461ae115bc7Smrj (void) memset(opp2->oprom_array + varlen2, '\0',
462ae115bc7Smrj PW_SIZE);
463ae115bc7Smrj opp2->oprom_size = varlen2 + PW_SIZE;
464ae115bc7Smrj /* set mode first */
465ae115bc7Smrj if (setpropval(opp) || setpropval(opp2))
466ae115bc7Smrj exit(1);
467ae115bc7Smrj } else {
468ae115bc7Smrj if (setpropval(opp))
469ae115bc7Smrj exit(1);
470ae115bc7Smrj }
471ae115bc7Smrj } else {
472ae115bc7Smrj (void) printf("Invalid security mode, mode unchanged.\n");
473ae115bc7Smrj exit(1);
474ae115bc7Smrj }
475ae115bc7Smrj }
476ae115bc7Smrj
477ae115bc7Smrj /*
478ae115bc7Smrj * Set password.
479ae115bc7Smrj * We must be in a secure mode in order to do this.
480ae115bc7Smrj */
481ae115bc7Smrj /* ARGSUSED */
482ae115bc7Smrj static void
i_passwd(char * var,char * val,struct openpromio * opp)483ae115bc7Smrj i_passwd(char *var, char *val, struct openpromio *opp)
484ae115bc7Smrj {
485ae115bc7Smrj int secure;
486ae115bc7Smrj Oppbuf oppbuf;
487ae115bc7Smrj struct openpromio *opp2 = &(oppbuf.opp);
488ae115bc7Smrj char pwbuf[PW_SIZE + 2];
489ae115bc7Smrj int varlen;
490ae115bc7Smrj
491ae115bc7Smrj (void) strcpy(opp2->oprom_array, MODE_PROPERTY);
492ae115bc7Smrj if (getpropval(opp2) || opp2->oprom_size <= 0) {
493ae115bc7Smrj (void) printf("%s: data not available.\n", opp2->oprom_array);
494ae115bc7Smrj exit(1);
495ae115bc7Smrj }
496ae115bc7Smrj secure = strcmp(opp2->oprom_array, "none");
497ae115bc7Smrj
498ae115bc7Smrj if (!secure) {
499ae115bc7Smrj (void) printf("Not in secure mode\n");
500ae115bc7Smrj exit(1);
501ae115bc7Smrj }
502ae115bc7Smrj
503ae115bc7Smrj /* Set up opp for password */
504ae115bc7Smrj (void) strcpy(opp->oprom_array, var); /* Safe; We know the name */
505ae115bc7Smrj varlen = strlen(opp->oprom_array) + 1;
506ae115bc7Smrj
507ae115bc7Smrj if (get_password(pwbuf, PW_SIZE)) {
508ae115bc7Smrj (void) strcpy(opp->oprom_array + varlen, pwbuf); /* Bounded */
509ae115bc7Smrj opp->oprom_size = varlen + strlen(pwbuf);
510ae115bc7Smrj if (setpropval(opp))
511ae115bc7Smrj exit(1);
512ae115bc7Smrj } else
513ae115bc7Smrj exit(1);
514ae115bc7Smrj }
515ae115bc7Smrj
516ae115bc7Smrj /* ARGSUSED */
517ae115bc7Smrj static void
o_passwd(char * var,char * val)518ae115bc7Smrj o_passwd(char *var, char *val)
519ae115bc7Smrj {
520ae115bc7Smrj /* Don't print the password */
521ae115bc7Smrj }
522ae115bc7Smrj
523ae115bc7Smrj static int
get_password(char * pw_dest,int pwsize)524ae115bc7Smrj get_password(char *pw_dest, int pwsize)
525ae115bc7Smrj {
526ae115bc7Smrj int insist = 0, ok, flags;
527ae115bc7Smrj int c, pwlen;
528ae115bc7Smrj char *p;
529ae115bc7Smrj static char pwbuf[256];
530ae115bc7Smrj char *pasword = NULL;
531ae115bc7Smrj
532ae115bc7Smrj tryagain:
533ae115bc7Smrj (void) printf("Changing PROM password:\n");
534ae115bc7Smrj if ((pasword = getpass("New password:")) == NULL) {
535ae115bc7Smrj exit(_error(NO_PERROR, "failed to get password"));
536ae115bc7Smrj }
537ae115bc7Smrj (void) strcpy(pwbuf, pasword);
538ae115bc7Smrj pwlen = strlen(pwbuf);
539ae115bc7Smrj if (pwlen == 0) {
540ae115bc7Smrj (void) printf("Password unchanged.\n");
541ae115bc7Smrj return (0);
542ae115bc7Smrj }
543ae115bc7Smrj /*
544ae115bc7Smrj * Insure password is of reasonable length and
545ae115bc7Smrj * composition. If we really wanted to make things
546ae115bc7Smrj * sticky, we could check the dictionary for common
547ae115bc7Smrj * words, but then things would really be slow.
548ae115bc7Smrj */
549ae115bc7Smrj ok = 0;
550ae115bc7Smrj flags = 0;
551ae115bc7Smrj p = pwbuf;
552ae115bc7Smrj while ((c = *p++) != 0) {
553ae115bc7Smrj if (c >= 'a' && c <= 'z')
554ae115bc7Smrj flags |= 2;
555ae115bc7Smrj else if (c >= 'A' && c <= 'Z')
556ae115bc7Smrj flags |= 4;
557ae115bc7Smrj else if (c >= '0' && c <= '9')
558ae115bc7Smrj flags |= 1;
559ae115bc7Smrj else
560ae115bc7Smrj flags |= 8;
561ae115bc7Smrj }
562ae115bc7Smrj if (flags >= 7 && pwlen >= 4)
563ae115bc7Smrj ok = 1;
564ae115bc7Smrj if ((flags == 2 || flags == 4) && pwlen >= 6)
565ae115bc7Smrj ok = 1;
566ae115bc7Smrj if ((flags == 3 || flags == 5 || flags == 6) && pwlen >= 5)
567ae115bc7Smrj ok = 1;
568ae115bc7Smrj if (!ok && insist < 2) {
569ae115bc7Smrj (void) printf("Please use %s.\n", flags == 1 ?
570ae115bc7Smrj "at least one non-numeric character" : "a longer password");
571ae115bc7Smrj insist++;
572ae115bc7Smrj goto tryagain;
573ae115bc7Smrj }
574ae115bc7Smrj if (strcmp(pwbuf, getpass("Retype new password:")) != 0) {
575ae115bc7Smrj (void) printf("Mismatch - password unchanged.\n");
576ae115bc7Smrj return (0);
577ae115bc7Smrj }
578ae115bc7Smrj (void) strncpy(pw_dest, pwbuf, pwsize);
579ae115bc7Smrj return (1);
580ae115bc7Smrj }
581