2 * Open Boot Prom eeprom utility
6 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
10 * Copyright (c) 1983 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <sys/openpromio.h>
26 * Usage: % eeprom [-v] [-f promdev] [-]
27 * % eeprom [-v] [-f promdev] field[=value] ...
31 * 128 is the size of the largest (currently) property name buffer
32 * 8192 - MAXPROPSIZE - sizeof (int) is the size of the largest
33 * (currently) property value, viz. nvramrc.
34 * the sizeof(u_int) is from struct openpromio
37 #define MAXPROPSIZE 128
38 #define MAXNAMESIZE MAXPROPSIZE
39 #define MAXVALSIZE (8192 - MAXPROPSIZE - sizeof (uint_t))
40 #define BUFSIZE (MAXPROPSIZE + MAXVALSIZE + sizeof (uint_t))
43 struct openpromio opp
;
46 extern int _error(int do_perror
, char *fmt
, ...);
47 extern void setpname(char *);
48 static int get_password(char *, int);
49 extern int loadlogo(char *, int, int, char *);
58 static void do_var(char *);
59 static void dump_all();
60 static void print_one(char *);
61 static void set_one(char *, char *);
62 static void promclose();
63 static int promopen(int);
65 static int getpropval(struct openpromio
*);
66 static int setpropval(struct openpromio
*);
68 static char *badarchmsg
= "Architecture does not support this command.\n";
70 typedef void (*func
)();
73 /* We have to special-case two properties related to security */
74 static void i_secure();
75 static void i_passwd(), o_passwd();
76 static void i_oemlogo();
79 * It's unfortunate that we have to know the names of certain properties
80 * in this program (the whole idea of openprom was to avoid it), but at
81 * least we can isolate them to these defines here.
83 #define PASSWORD_PROPERTY "security-password"
84 #define MODE_PROPERTY "security-mode"
85 #define LOGO_PROPERTY "oem-logo"
89 * Unlike the old-style eeprom command, where every property needed an
90 * i_foo and an o_foo function, we only need them when the default case
98 #define e(n, i, o) {n, i, o}
99 e(MODE_PROPERTY
, i_secure
, (func
)NULL
),
100 e(PASSWORD_PROPERTY
, i_passwd
, o_passwd
),
101 e(LOGO_PROPERTY
, i_oemlogo
, (func
)NULL
),
102 { (char *)NULL
, (func
)NULL
, (func
)NULL
}
112 main(int argc
, char **argv
)
118 promdev
= "/dev/openprom";
120 while ((c
= getopt(argc
, argv
, "cif:v")) != -1)
124 /* ignore for openprom */
133 exit(_error(NO_PERROR
,
134 "Usage: %s [-v] [-f prom-device] "
135 "[variable[=value] ...]", argv
[0]));
141 * If no arguments, dump all fields.
143 if (optind
>= argc
) {
148 while (optind
< argc
) {
150 * If "-" specified, read variables from stdin.
152 if (strcmp(argv
[optind
], "-") == 0) {
154 char *nl
, line
[BUFSIZE
];
156 while (fgets(line
, sizeof (line
), stdin
) != NULL
) {
157 /* zap newline if present */
158 if (nl
= strchr(line
, '\n'))
160 /* otherwise discard rest of line */
162 while ((c
= getchar()) != '\n' &&
171 * Process each argument as a variable print or set request.
174 do_var(argv
[optind
]);
182 * Print or set an EEPROM field.
189 val
= strchr(var
, '=');
193 * print specific property
195 if (promopen(O_RDONLY
)) {
196 (void) fprintf(stderr
, badarchmsg
);
202 * set specific property to value
206 if (promopen(O_RDWR
)) {
207 (void) fprintf(stderr
, badarchmsg
);
216 * Print all properties and values
222 struct openpromio
*opp
= &(oppbuf
.opp
);
224 if (promopen(O_RDONLY
)) {
225 (void) fprintf(stderr
, badarchmsg
);
228 /* get first prop by asking for null string */
229 (void) memset(oppbuf
.buf
, '\0', BUFSIZE
);
235 opp
->oprom_size
= MAXPROPSIZE
;
237 if (ioctl(prom_fd
, OPROMNXTOPT
, opp
) < 0)
238 exit(_error(PERROR
, "OPROMNXTOPT"));
240 if (opp
->oprom_size
== 0) {
244 print_one(opp
->oprom_array
);
249 * Print one property and its value.
255 struct openpromio
*opp
= &(oppbuf
.opp
);
256 char bootargs
[MAXVALSIZE
];
258 if (strcmp(var
, "bootcmd") == 0) {
259 opp
->oprom_size
= MAXVALSIZE
;
260 if (ioctl(prom_fd
, OPROMGETBOOTARGS
, opp
) < 0) {
261 (void) _error(PERROR
, "OPROMGETBOOTARGS");
264 (void) strlcpy(bootargs
, opp
->oprom_array
, MAXVALSIZE
);
266 opp
->oprom_size
= MAXVALSIZE
;
267 if (ioctl(prom_fd
, OPROMGETBOOTPATH
, opp
) < 0) {
268 (void) _error(PERROR
, "OPROMGETBOOTPATH");
271 (void) printf("%s=%s %s\n", var
, opp
->oprom_array
, bootargs
);
275 (void) strlcpy(opp
->oprom_array
, var
, MAXNAMESIZE
);
276 if (getpropval(opp
) || opp
->oprom_size
<= 0)
277 (void) printf("%s: data not available.\n", var
);
279 /* If necessary, massage the output */
282 for (v
= opvar
; v
->name
; v
++)
283 if (strcmp(var
, v
->name
) == 0)
286 if (v
->name
&& v
->out
)
287 (*v
->out
)(v
->name
, opp
->oprom_array
);
289 (void) printf("%s=%s\n", var
, opp
->oprom_array
);
294 * Set one property to the given value.
297 set_one(char *var
, char *val
)
300 struct openpromio
*opp
= &(oppbuf
.opp
);
304 (void) printf("old:");
308 /* If necessary, massage the input */
310 for (v
= opvar
; v
->name
; v
++)
311 if (strcmp(var
, v
->name
) == 0)
314 if (v
->name
&& v
->in
)
315 (*v
->in
)(v
->name
, val
, opp
);
317 int varlen
= strlen(var
) + 1;
318 int vallen
= strlen(val
);
320 if (varlen
> MAXNAMESIZE
) {
321 (void) printf("%s: invalid property.\n", var
);
324 if (vallen
>= MAXVALSIZE
) {
325 (void) printf("%s: invalid property value.\n", var
);
328 (void) strcpy(opp
->oprom_array
, var
);
329 (void) strcpy(opp
->oprom_array
+ varlen
, val
);
330 opp
->oprom_size
= varlen
+ vallen
;
332 (void) printf("%s: invalid property.\n", var
);
336 (void) printf("new:");
346 if ((prom_fd
= open(promdev
, oflag
)) < 0) {
349 else if (errno
== ENXIO
)
352 exit(_error(PERROR
, "cannot open %s", promdev
));
362 if (close(prom_fd
) < 0)
363 exit(_error(PERROR
, "close error on %s", promdev
));
367 getpropval(struct openpromio
*opp
)
369 opp
->oprom_size
= MAXVALSIZE
;
371 if (ioctl(prom_fd
, OPROMGETOPT
, opp
) < 0)
372 return (_error(PERROR
, "OPROMGETOPT"));
378 setpropval(struct openpromio
*opp
)
380 /* Caller must set opp->oprom_size */
382 if (ioctl(prom_fd
, OPROMSETOPT
, opp
) < 0)
383 return (_error(PERROR
, "OPROMSETOPT"));
389 * The next set of functions handle the special cases.
393 i_oemlogo(char *var
, char *val
, struct openpromio
*opp
)
395 int varlen
= strlen(var
) + 1;
397 (void) strcpy(opp
->oprom_array
, var
); /* safe - we know the name */
399 if (loadlogo(val
, 64, 64, opp
->oprom_array
+ varlen
))
401 opp
->oprom_size
= varlen
+ 512;
402 if (ioctl(prom_fd
, OPROMSETOPT2
, opp
) < 0)
403 exit(_error(PERROR
, "OPROMSETOPT2"));
408 * If oldmode was none, and new mode is not none, get and set password,
410 * If old mode was not none, and new mode is none, wipe out old
414 i_secure(char *var
, char *val
, struct openpromio
*opp
)
418 struct openpromio
*opp2
= &(oppbuf
.opp
);
419 char pwbuf
[PW_SIZE
+ 2];
420 int varlen1
, varlen2
;
422 (void) strcpy(opp2
->oprom_array
, var
); /* safe; we know the name */
423 if (getpropval(opp2
) || opp2
->oprom_size
<= 0) {
424 (void) printf("%s: data not available.\n", var
);
427 secure
= strcmp(opp2
->oprom_array
, "none");
429 /* Set up opp for mode */
430 (void) strcpy(opp
->oprom_array
, var
); /* safe; we know the name */
431 varlen1
= strlen(opp
->oprom_array
) + 1;
432 if (strlen(val
) > 32) { /* 32 > [ "full", "command", "none" ] */
433 (void) printf("Invalid security mode, mode unchanged.\n");
436 (void) strcpy(opp
->oprom_array
+ varlen1
, val
);
437 opp
->oprom_size
= varlen1
+ strlen(val
);
439 /* Set up opp2 for password */
440 (void) strcpy(opp2
->oprom_array
, PASSWORD_PROPERTY
);
441 varlen2
= strlen(opp2
->oprom_array
) + 1;
443 if ((strcmp(val
, "full") == 0) || (strcmp(val
, "command") == 0)) {
445 /* no password yet, get one */
446 if (get_password(pwbuf
, PW_SIZE
)) {
447 (void) strcpy(opp2
->oprom_array
+ varlen2
,
449 opp2
->oprom_size
= varlen2
+ strlen(pwbuf
);
450 /* set password first */
451 if (setpropval(opp2
) || setpropval(opp
))
459 } else if (strcmp(val
, "none") == 0) {
461 (void) memset(opp2
->oprom_array
+ varlen2
, '\0',
463 opp2
->oprom_size
= varlen2
+ PW_SIZE
;
465 if (setpropval(opp
) || setpropval(opp2
))
472 (void) printf("Invalid security mode, mode unchanged.\n");
479 * We must be in a secure mode in order to do this.
483 i_passwd(char *var
, char *val
, struct openpromio
*opp
)
487 struct openpromio
*opp2
= &(oppbuf
.opp
);
488 char pwbuf
[PW_SIZE
+ 2];
491 (void) strcpy(opp2
->oprom_array
, MODE_PROPERTY
);
492 if (getpropval(opp2
) || opp2
->oprom_size
<= 0) {
493 (void) printf("%s: data not available.\n", opp2
->oprom_array
);
496 secure
= strcmp(opp2
->oprom_array
, "none");
499 (void) printf("Not in secure mode\n");
503 /* Set up opp for password */
504 (void) strcpy(opp
->oprom_array
, var
); /* Safe; We know the name */
505 varlen
= strlen(opp
->oprom_array
) + 1;
507 if (get_password(pwbuf
, PW_SIZE
)) {
508 (void) strcpy(opp
->oprom_array
+ varlen
, pwbuf
); /* Bounded */
509 opp
->oprom_size
= varlen
+ strlen(pwbuf
);
518 o_passwd(char *var
, char *val
)
520 /* Don't print the password */
524 get_password(char *pw_dest
, int pwsize
)
526 int insist
= 0, ok
, flags
;
529 static char pwbuf
[256];
530 char *pasword
= NULL
;
533 (void) printf("Changing PROM password:\n");
534 if ((pasword
= getpass("New password:")) == NULL
) {
535 exit(_error(NO_PERROR
, "failed to get password"));
537 (void) strcpy(pwbuf
, pasword
);
538 pwlen
= strlen(pwbuf
);
540 (void) printf("Password unchanged.\n");
544 * Insure password is of reasonable length and
545 * composition. If we really wanted to make things
546 * sticky, we could check the dictionary for common
547 * words, but then things would really be slow.
552 while ((c
= *p
++) != 0) {
553 if (c
>= 'a' && c
<= 'z')
555 else if (c
>= 'A' && c
<= 'Z')
557 else if (c
>= '0' && c
<= '9')
562 if (flags
>= 7 && pwlen
>= 4)
564 if ((flags
== 2 || flags
== 4) && pwlen
>= 6)
566 if ((flags
== 3 || flags
== 5 || flags
== 6) && pwlen
>= 5)
568 if (!ok
&& insist
< 2) {
569 (void) printf("Please use %s.\n", flags
== 1 ?
570 "at least one non-numeric character" : "a longer password");
574 if (strcmp(pwbuf
, getpass("Retype new password:")) != 0) {
575 (void) printf("Mismatch - password unchanged.\n");
578 (void) strncpy(pw_dest
, pwbuf
, pwsize
);