openprom.c revision 23a1ccea6aac035f084a7a4cdc968687d1b02daf
/*
* Open Boot Prom eeprom utility
*/
/*
*/
/*
* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#include <sys/openpromio.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
/*
* Usage: % eeprom [-v] [-f promdev] [-]
* % eeprom [-v] [-f promdev] field[=value] ...
*/
/*
* 128 is the size of the largest (currently) property name buffer
* 8192 - MAXPROPSIZE - sizeof (int) is the size of the largest
* (currently) property value, viz. nvramrc.
* the sizeof(u_int) is from struct openpromio
*/
#define MAXPROPSIZE 128
#define MAXNAMESIZE MAXPROPSIZE
typedef union {
struct openpromio opp;
} Oppbuf;
extern void setpname(char *);
static int get_password(char *, int);
extern int loadlogo(char *, int, int, char *);
#define NO_PERROR 0
#define PERROR 1
static int prom_fd;
static char *promdev;
static int verbose;
static void do_var(char *);
static void dump_all();
static void print_one(char *);
static void set_one(char *, char *);
static void promclose();
static int promopen(int);
static int getpropval(struct openpromio *);
static int setpropval(struct openpromio *);
static char *badarchmsg = "Architecture does not support this command.\n";
typedef void (*func)();
/* We have to special-case two properties related to security */
static void i_secure();
static void i_oemlogo();
/*
* It's unfortunate that we have to know the names of certain properties
* in this program (the whole idea of openprom was to avoid it), but at
* least we can isolate them to these defines here.
*/
#define PASSWORD_PROPERTY "security-password"
#define MODE_PROPERTY "security-mode"
#define LOGO_PROPERTY "oem-logo"
#define PW_SIZE 8
/*
* Unlike the old-style eeprom command, where every property needed an
* i_foo and an o_foo function, we only need them when the default case
* isn't sufficient.
*/
static struct opvar {
char *name;
} opvar[] = {
#define e(n, i, o) {n, i, o}
#undef e
};
/*
* sun4c openprom
*/
int
{
int c;
extern char *optarg;
extern int optind;
switch (c) {
case 'c':
case 'i':
/* ignore for openprom */
break;
case 'v':
verbose++;
break;
case 'f':
break;
default:
"Usage: %s [-v] [-f prom-device] "
"[variable[=value] ...]", argv[0]));
}
/*
* If no arguments, dump all fields.
*/
dump_all();
exit(0);
}
/*
* If "-" specified, read variables from stdin.
*/
int c;
/* zap newline if present */
*nl = 0;
/* otherwise discard rest of line */
else
while ((c = getchar()) != '\n' &&
c != EOF)
/* nothing */;
}
}
/*
* Process each argument as a variable print or set request.
*/
else
optind++;
}
return (0);
}
/*
* Print or set an EEPROM field.
*/
static void
{
char *val;
/*
* print specific property
*/
exit(1);
}
} else {
/*
* set specific property to value
*/
*val++ = '\0';
exit(1);
}
}
promclose();
}
/*
* Print all properties and values
*/
static void
dump_all()
{
exit(1);
}
/* get first prop by asking for null string */
/* CONSTCOND */
while (1) {
/*
* get property
*/
if (opp->oprom_size == 0) {
promclose();
return;
}
}
}
/*
* Print one property and its value.
*/
static void
{
char bootargs[MAXVALSIZE];
return;
}
return;
}
return;
}
else {
/* If necessary, massage the output */
struct opvar *v;
break;
else
}
}
/*
* Set one property to the given value.
*/
static void
{
struct opvar *v;
if (verbose) {
(void) printf("old:");
}
/* If necessary, massage the input */
break;
else {
if (varlen > MAXNAMESIZE) {
return;
}
if (vallen >= MAXVALSIZE) {
return;
}
if (setpropval(opp))
}
if (verbose) {
(void) printf("new:");
}
}
static int
{
/* CONSTCOND */
while (1) {
continue;
return (-1);
else
} else
break;
}
return (0);
}
static void
{
}
static int
{
return (0);
}
static int
{
/* Caller must set opp->oprom_size */
return (0);
}
/*
* The next set of functions handle the special cases.
*/
static void
{
exit(1);
}
/*
* Set security mode.
* If oldmode was none, and new mode is not none, get and set password,
* too.
* If old mode was not none, and new mode is none, wipe out old
* password.
*/
static void
{
int secure;
exit(1);
}
/* Set up opp for mode */
(void) printf("Invalid security mode, mode unchanged.\n");
exit(1);
}
/* Set up opp2 for password */
if (! secure) {
/* no password yet, get one */
pwbuf);
/* set password first */
exit(1);
} else
exit(1);
} else {
if (setpropval(opp))
exit(1);
}
if (secure) {
PW_SIZE);
/* set mode first */
exit(1);
} else {
if (setpropval(opp))
exit(1);
}
} else {
(void) printf("Invalid security mode, mode unchanged.\n");
exit(1);
}
}
/*
* Set password.
* We must be in a secure mode in order to do this.
*/
/* ARGSUSED */
static void
{
int secure;
int varlen;
exit(1);
}
if (!secure) {
(void) printf("Not in secure mode\n");
exit(1);
}
/* Set up opp for password */
if (setpropval(opp))
exit(1);
} else
exit(1);
}
/* ARGSUSED */
static void
{
/* Don't print the password */
}
static int
{
int c, pwlen;
char *p;
static char pwbuf[256];
(void) printf("Changing PROM password:\n");
}
if (pwlen == 0) {
(void) printf("Password unchanged.\n");
return (0);
}
/*
* Insure password is of reasonable length and
* composition. If we really wanted to make things
* sticky, we could check the dictionary for common
* words, but then things would really be slow.
*/
ok = 0;
flags = 0;
p = pwbuf;
while ((c = *p++) != 0) {
if (c >= 'a' && c <= 'z')
flags |= 2;
else if (c >= 'A' && c <= 'Z')
flags |= 4;
else if (c >= '0' && c <= '9')
flags |= 1;
else
flags |= 8;
}
ok = 1;
ok = 1;
ok = 1;
"at least one non-numeric character" : "a longer password");
insist++;
goto tryagain;
}
(void) printf("Mismatch - password unchanged.\n");
return (0);
}
return (1);
}