xref: /titanic_44/usr/src/cmd/eeprom/sparc/openprom.c (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
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