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