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