845 lines
22 KiB
C
845 lines
22 KiB
C
/*
|
|
* env.c - handle FLASH based environment variables.
|
|
*
|
|
* Ok, why a separate EV module. The standard implementation has the
|
|
* EV code broken up into several modules and is organized around NVRAM,
|
|
* not flash. The means of storing EV's in FLASH is somewhat different
|
|
* than for NVRAM so a lot of minor changes are required across several
|
|
* modules and these modules are shared by other platforms. This env.c
|
|
* module handles all the details of EV's in one place except for the
|
|
* FLASH management. It's easier to understand and won't break any of
|
|
* the other platforms. Whether or not these changes will make it into
|
|
* the common code remains to be seen.
|
|
*/
|
|
|
|
/*
|
|
* NOTE: Ill-formed EV string (i.e. not in the form "name=value....") are
|
|
* not generally detected and will probably cause problems.
|
|
*/
|
|
|
|
#include <sys/cpu.h>
|
|
#include <sys/IP32flash.h>
|
|
#include <arcs/errno.h>
|
|
#include <sys/types.h>
|
|
#include <stringlist.h>
|
|
#include <saioctl.h>
|
|
#include <arcs/io.h>
|
|
#include <libsc.h>
|
|
#include <libsk.h>
|
|
#include <flash.h>
|
|
#include <assert.h>
|
|
|
|
/*
|
|
* NOTE::::::::::::
|
|
* DUE TO THE PROBLEM WE RAN INTO IN THE LAB WHEN PROGRAM THE FLASH
|
|
* WE DISABLE THE FLASH WRITE FOR NOW.
|
|
*/
|
|
/* #define LABnoFlash */
|
|
/* #define ENVDEBUG */
|
|
|
|
/*
|
|
* Forward definitions
|
|
*/
|
|
static void initialize_envstrs(void);
|
|
static void reconstruct_envstrs(void);
|
|
static int updateFlashEV(int unset, char* name, char* value, int override);
|
|
static char* extractEVN(char* str, char* buf);
|
|
|
|
/*
|
|
* External definitions
|
|
*/
|
|
extern struct string_list environ_str;
|
|
extern char** environ;
|
|
extern char netaddr_default[];
|
|
extern void DPRINTF(char *, ...);
|
|
extern void cpu_get_eaddr_str(char*);
|
|
extern void garbage_collect(struct string_list *);
|
|
|
|
/* Standard EV's (This should come from an include file.)*/
|
|
|
|
#define PASSWD "passwd_key"
|
|
#define NETPASSWD "netpasswd_key"
|
|
/* #define MACE2ECBUG 1 */
|
|
#undef MACE2ECBUG
|
|
|
|
static char nullStr[] = "";
|
|
struct evTable{
|
|
char* name;
|
|
char* defaultValue;
|
|
int options;
|
|
}env_table[] = {
|
|
{"OSLoadOptions", nullStr, 0},
|
|
{"SystemPartition", nullStr, 0},
|
|
{"OSLoadPartition", nullStr, 0},
|
|
{"OSLoader", nullStr, 0},
|
|
{"OSLoadFilename", nullStr, 0},
|
|
#if defined(IP32SIM)
|
|
{"AutoLoad", "No", 0},
|
|
#else
|
|
{"AutoLoad", "Yes", 0},
|
|
#endif
|
|
{"rbaud", nullStr, 0},
|
|
{"console", "g", 0},
|
|
{"diagmode", nullStr, 0},
|
|
{"diskless", "0", 0},
|
|
{"nogfxkbd", nullStr, 0},
|
|
{"keybd", nullStr, 0},
|
|
{"lang", nullStr, 0},
|
|
{"scsiretries", nullStr, 0},
|
|
{"scsihostid", nullStr, 0},
|
|
{"dbaud", "9600", 0},
|
|
{"pagecolor", nullStr, 0},
|
|
{"volume", "80", 0},
|
|
{"sgilogo", "y", 0},
|
|
{"nogui", nullStr, 0},
|
|
{"monitor", "h", 0},
|
|
{PASSWD, nullStr, 0},
|
|
{NETPASSWD, nullStr, 0},
|
|
{"TimeZone", "PST8PDT", 0},
|
|
{"netaddr", netaddr_default, 0},
|
|
#if defined(MACE2ECBUG)
|
|
{"ec0mode", "H10", 0},
|
|
#endif
|
|
#undef MACE2ECBUG
|
|
{0, 0, 0}
|
|
};
|
|
|
|
/* The EV's in special_tab have special handling associated with them */
|
|
|
|
#define SENV_READONLY 1
|
|
#define VARIABLE 2
|
|
#define SENV_LOCKNVRAM 4
|
|
|
|
extern int Debug, Verbose, _udpcksum;
|
|
|
|
static struct special {
|
|
char *name;
|
|
int *value;
|
|
int flags;
|
|
} special_tab[] = {
|
|
{"DEBUG", &Debug, VARIABLE},
|
|
{"VERBOSE", &Verbose, VARIABLE},
|
|
{"_udpcksum", &_udpcksum, VARIABLE},
|
|
{"gfx", 0, SENV_READONLY},
|
|
{"cpufreq", 0, SENV_READONLY},
|
|
{"eaddr", 0, SENV_READONLY},
|
|
{0,0,0}
|
|
};
|
|
|
|
|
|
/* Pointer to the FLASH segment containing the EV's. If zero, we ignore FLASH*/
|
|
|
|
static FlashSegment* flashSeg;
|
|
|
|
/*********
|
|
* _setenv
|
|
* -------
|
|
* Set the value of an EV.
|
|
*
|
|
* If the value is 0 or the null string, unset the EV.
|
|
* If the EV requires special handling, invoke it.
|
|
* If override is 1, override the READONLY special processing flag.
|
|
* If override is 2, make the EV persistent.
|
|
*
|
|
* Return EACCES if the EV is readonly (by updateFlashEV())
|
|
*/
|
|
int
|
|
_setenv (char *name, char *value, int override)
|
|
{
|
|
int unset = (value == 0) || (*value == '\0');
|
|
static struct special* special;
|
|
|
|
/* The passwd can only be reset by syssetenv, no others */
|
|
if (unset &&
|
|
((strcmp(name,PASSWD)==0)||(strcmp(name,NETPASSWD)==0)) &&
|
|
!override)
|
|
return 0;
|
|
|
|
/* Scan the special processing table and invoke any special processing.*/
|
|
for (special = special_tab; special->name; special++){
|
|
if (strcasecmp (name, special->name)==0) {
|
|
if (override != 1 && (special->flags & SENV_READONLY))
|
|
return EACCES;
|
|
if (special->flags & VARIABLE)
|
|
if (unset)
|
|
*special->value = 0;
|
|
else
|
|
atob(value, special->value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We update environ_str before we update the FLASH because FLASH is updated
|
|
* from environ_str. Note that if the environ_str update fails, we don't know
|
|
* it and a spurious FLASH update occurs.
|
|
*/
|
|
|
|
if (unset)
|
|
delete_str(name, &environ_str);
|
|
else
|
|
replace_str(name, value, &environ_str);
|
|
|
|
/* updateFlashEV should return correct stuff if we set the flashSeq to 0 */
|
|
return updateFlashEV(unset,name,value,override);
|
|
}
|
|
|
|
|
|
|
|
/**********
|
|
* init_env
|
|
* --------
|
|
* Load or reconstruct EV table
|
|
*/
|
|
char CPUeaddr[] = "ff:ff:ff:ff:ff:ff" ;
|
|
void
|
|
init_env(void)
|
|
{
|
|
char* cp;
|
|
|
|
/* Initialize an empty string table to hold the EV's */
|
|
init_str(&environ_str);
|
|
|
|
/* Locate the EV's in flash */
|
|
#if defined(LABnoFlash)
|
|
flashSeg = 0 ;
|
|
#else
|
|
flashSeg = findFlashSegment(&envFlash,ENV_FLASH_SEGMENT,0);
|
|
#endif
|
|
|
|
/*
|
|
* Check for valid FLASH contents for platform. If it's ok, reload the
|
|
* EV's from FLASH. If not ok, reconstruct the EV's from the default table.
|
|
*/
|
|
if (flashSeg) { /* Check for an empty env segment. */
|
|
if (*(char*)body(flashSeg)) { /* we have a valid non-empty env segment */
|
|
initialize_envstrs();
|
|
} else { /* Found an empty but yet valid env segment. */
|
|
reconstruct_envstrs();
|
|
}
|
|
} else { /* There is no env segment in the flash at all. */
|
|
reconstruct_envstrs();
|
|
}
|
|
|
|
/*
|
|
* environ is passed to exec'ed images. Point it at the EV strings.
|
|
*/
|
|
environ = environ_str.strptrs;
|
|
|
|
/*
|
|
* Set EV values derived from other values or other state.
|
|
*/
|
|
init_consenv(0); /* Derives ConsoleIn/Out from console */
|
|
if (cp = cpu_get_freq_str(0)) /* Computes cpu frequency and sets EV */
|
|
syssetenv("cpufreq",cp); /* And set it in the evStr variable. */
|
|
cpu_get_eaddr_str(CPUeaddr); /* get the eaddr frome ds2506 */
|
|
syssetenv("eaddr",CPUeaddr); /* and set the eaddr ENV */
|
|
|
|
#if 0
|
|
/*
|
|
* BUG# 380812 - MH PROM can't save console to d
|
|
* We need to assign the environ variable the real EV string address
|
|
* before we call to set those special EV values derived from other
|
|
* values or other state.
|
|
*/
|
|
/*
|
|
* environ is passed to exec'ed images. Point it at the EV strings.
|
|
*/
|
|
environ = environ_str.strptrs;
|
|
#endif
|
|
}
|
|
|
|
|
|
/************
|
|
* extractEVV
|
|
* ----------
|
|
* Copy "name" from head of "name=xxxxx" to buffer.
|
|
* Return ptr to "xxxxx".
|
|
*/
|
|
static char*
|
|
extractEVV(char* str)
|
|
{
|
|
assert(str);
|
|
while (*str!= '=') str++;
|
|
|
|
/* If string is ill-formed, return 0, otherwise ptr to value */
|
|
return (*str!='=') ? 0 : str + 1;
|
|
}
|
|
|
|
/************
|
|
* extractEVN
|
|
* ----------
|
|
* Copy "name" from head of "name=xxxxx" to buffer.
|
|
* Return ptr to "xxxxx".
|
|
*/
|
|
static char*
|
|
extractEVN(char* str, char* buf)
|
|
{
|
|
char* bp = buf;
|
|
assert(str);
|
|
assert(buf);
|
|
while (*str && *str!= '=')
|
|
*bp++ = *str++;
|
|
*bp = 0;
|
|
|
|
/* If string is ill-formed, return 0, otherwise ptr to value */
|
|
return (*str!='=') ? 0 : str + 1;
|
|
}
|
|
|
|
/***************
|
|
* persistentEVN
|
|
*--------------
|
|
* Indicate if EVN is persistent.
|
|
* Instead of returning true/false, we return a pointer to the current
|
|
* value of the EV if it is persistent, and 0 if it is not. Clients can
|
|
* compare the value and suppress unneeded updates.
|
|
*/
|
|
static char*
|
|
persistentEVN(char* evn)
|
|
{
|
|
struct evTable* ev;
|
|
char* str2;
|
|
int len;
|
|
|
|
assert(evn);
|
|
|
|
len = strlen(evn);
|
|
|
|
/* If the EV is in the flash segment, it's persistent. */
|
|
if (flashSeg) {
|
|
for (str2 = (char*)body(flashSeg); *str2; str2 += strlen(str2)+1) {
|
|
if (strncasecmp(evn,str2,len)==0 && str2[len]=='=')
|
|
return &str2[len+1];
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the EV is in env_table, it's persistent. (Note, this could
|
|
* be changed to be controlled by an option bit.) If flashSeg
|
|
* is defined, we shouldn't get here because the flash segment should
|
|
* already contain the EV and we should have hit it above. However,
|
|
* flashSeg may not be defined.
|
|
*/
|
|
for (ev = env_table;ev->name;ev++)
|
|
if (strcasecmp(ev->name,evn)==0)
|
|
return ev->defaultValue;
|
|
return 0;
|
|
}
|
|
|
|
/**************
|
|
* persistentEV
|
|
* ------------
|
|
* Return true if EV is preserved in nvram/flash
|
|
* Similar to persistentEVN except the argument is name=value, not
|
|
* just the EV name.
|
|
*/
|
|
static int
|
|
persistentEV(char* str){
|
|
#if defined(LABnoFlash)
|
|
return 0 ;
|
|
#else
|
|
char evn[64];
|
|
extractEVN(str,evn);
|
|
return persistentEVN(evn)!=0;
|
|
#endif
|
|
}
|
|
|
|
/***************
|
|
* updateFlashEV
|
|
* -------------
|
|
* Update an EV in FLASH
|
|
*
|
|
* We are called with the name of an EV to update in flash. If the EV is
|
|
* not persistent and we are not promoting it to persistent, we do nothing.
|
|
* If the EV is not persistent and we are promoting it (override==2) then
|
|
* we perform a "promote" operation. If the EV is already persistent and we
|
|
* are not deleting it, we performa an "update all" operation. If the EV
|
|
* is persistent and we are deleteing it, we perform a delete action.
|
|
*/
|
|
static int
|
|
updateFlashEV(int unset, char* name, char* value, int override)
|
|
{
|
|
char evbuf[STRINGBYTES], *evbp = evbuf;
|
|
char *currentValue;
|
|
int nameLen = strlen(name);
|
|
int sts = ESUCCESS;
|
|
int i;
|
|
|
|
/* If no flash segment is set up, quit quietly */
|
|
if (flashSeg==0) {
|
|
return ESUCCESS;
|
|
}
|
|
|
|
/* assert(sizeof(evbuf) <= bodySize(flashSeg)); */
|
|
if(sizeof(evbuf) > bodySize(flashSeg))
|
|
printf("STRINGBYTES > flash seg size\n");
|
|
assert(((long)evbuf & 3)==0); /* Paranoid check of evbuf (long*) alignment */
|
|
|
|
|
|
/*
|
|
* Check that the EV is persistent. If so, persistentEVN returns the address
|
|
* of the current value string. Otherwise it returns 0. If not persistent,
|
|
* and we are not making it persistent (e.g. override==2), quit. If the EV
|
|
* is persistent but we aren't changing it's value, we also quit.
|
|
*/
|
|
currentValue = persistentEVN(name);
|
|
if ((currentValue==0 && override!=2) ||
|
|
(currentValue!=0 && strcmp(value,currentValue)==0))
|
|
return ESUCCESS;
|
|
|
|
/*
|
|
* Look at each name (evn) in environ_str and either skip it or
|
|
* copy it to evbuf.
|
|
*
|
|
* | ==name | persistent | unset | override==2 || ACTION
|
|
* ---+---------+------------+--------+-------------++-------
|
|
* 0 | 0 | 0 | 0 | 0 || skip 0
|
|
* 1 | 0 | 0 | 0 | 1 || skip 0
|
|
* 2 | 0 | 0 | 1 | 0 || skip 0
|
|
* 3 | 0 | 0 | 1 | 1 || skip * 0
|
|
* 4 | 0 | 1 | 0 | 0 || copy 1
|
|
* 5 | 0 | 1 | 0 | 1 || copy 1
|
|
* 6 | 0 | 1 | 1 | 0 || skip 0
|
|
* 7 | 0 | 1 | 1 | 1 || skip * 0
|
|
* ---+---------+------------+--------+-------------++-------
|
|
* 8 | 1 | 0 | 0 | 0 || skip 0
|
|
* 9 | 1 | 0 | 0 | 1 || copy 1
|
|
* 10 | 1 | 0 | 1 | 0 || skip 0
|
|
* 11 | 1 | 0 | 1 | 1 || skip * 0
|
|
* 12 | 1 | 1 | 0 | 0 || copy 1
|
|
* 13 | 1 | 1 | 0 | 1 || copy 1
|
|
* 14 | 1 | 1 | 1 | 0 || skip 0
|
|
* 15 | 1 | 1 | 1 | 1 || copy 1
|
|
* ---+---------+------------+--------+-------------++-------
|
|
*
|
|
* Note that the * actions are probably errors but we ignore them.
|
|
*/
|
|
for (i=0;i<environ_str.strcnt;i++){
|
|
char* ev = environ_str.strptrs[i];
|
|
int decode = 0;
|
|
|
|
/* Construct an index based on the decision table above */
|
|
if (override==2)
|
|
decode = 1;
|
|
#if 0
|
|
if (unset)
|
|
#endif
|
|
if (strncasecmp(ev,name,nameLen)==0 && unset)
|
|
decode |= 2;
|
|
if (persistentEV(ev))
|
|
decode |= 4;
|
|
if (strncasecmp(ev,name,nameLen)==0 && ev[nameLen]=='=')
|
|
decode |= 8;
|
|
|
|
|
|
/* 0xb230 is a bitmap of the "copy" actions from the above table. */
|
|
if ((0xb230>>decode)&1){
|
|
strcpy(evbp,ev);
|
|
evbp += strlen(ev)+1;
|
|
*evbp = 0;
|
|
}
|
|
#if defined(ENVDEBUG)
|
|
else {
|
|
printf ("DEBUG: skip %s\n", ev) ;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Rewrite the flash segment with the selected EV's */
|
|
if (sts = rewriteFlashSegment(&envFlash,flashSeg,(long*)evbuf))
|
|
printf("Error updating environment variables in FLASH\n");
|
|
return sts;
|
|
}
|
|
|
|
|
|
/*********************
|
|
* reconstruct_envstrs
|
|
* -------------------
|
|
* Called to rebuild EV's if NVRAM is invalid.
|
|
*/
|
|
static void
|
|
reconstruct_envstrs(void)
|
|
{
|
|
struct evTable* et;
|
|
|
|
/*
|
|
* Set default EV's from env_table
|
|
*/
|
|
for (et = env_table; et->name; et++) {
|
|
if (et->defaultValue != nullStr) {
|
|
if (syssetenv(et->name,et->defaultValue))
|
|
printf("Could not set environment variable %s.\n", et->name);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialize the EV segment.
|
|
* Note that we rely on environ_str being in a gc'ed state because
|
|
* environ_str was empty when we were called.
|
|
*/
|
|
#if !defined(LABnoFlash)
|
|
if (writeFlashSegment(&envFlash,
|
|
(FlashSegment*)PHYS_TO_K1(FLASH_PROGRAMABLE),
|
|
ENV_FLASH_SEGMENT,
|
|
ENV_FLASH_VSN,
|
|
(long*)environ_str.strbuf,
|
|
STRINGBYTES))
|
|
printf("Could not save environment variables in FLASH.\n");
|
|
else
|
|
flashSeg = (FlashSegment*)PHYS_TO_K1(FLASH_PROGRAMABLE);
|
|
#endif
|
|
}
|
|
|
|
/********************
|
|
* initialize_envstrs
|
|
* ------------------
|
|
* Called to load EV's from NVRAM.
|
|
* ------------------
|
|
*/
|
|
static void
|
|
initialize_envstrs()
|
|
{
|
|
FlashSegment* saveFlashSeg = flashSeg;
|
|
char* evStr = (char*)body(flashSeg);
|
|
struct evTable *et;
|
|
|
|
assert(flashSeg);
|
|
assert(environ_str.strcnt==0);
|
|
|
|
/*
|
|
* Because the EV may have special handling associated with it,
|
|
* we use _setenv to set each EV. Since _setenv will try to update the
|
|
* FLASH segment, we temporarily zero flashSeg to suppress those updates.
|
|
*/
|
|
flashSeg = 0;
|
|
for (evStr = (char*)body(saveFlashSeg); *evStr; evStr += strlen(evStr)+1) {
|
|
char evn[64];
|
|
if (_setenv(evn,extractEVN(evStr,evn),0))
|
|
printf("Could not set environment variable %s\n", evStr);
|
|
}
|
|
flashSeg = saveFlashSeg;
|
|
|
|
/*
|
|
* Now environ_str agrees with saveFlashSeg. However, now we want to
|
|
* check that all the persistent EV's in env_table are defined. A
|
|
* discrepency could arise if some other software deletes an entry
|
|
* in the FLASH segment or if we've updated the firmware and some new
|
|
* persistent EV's have been defined.
|
|
*
|
|
* We do this check by verifying that each entry in env_table is defined.
|
|
* Note that flashSeg has been restored so if have to add an entry, it
|
|
* will be pushed through to the FLASH.
|
|
*/
|
|
for (et = env_table; et->name; et++) {
|
|
if (!find_str(et->name,&environ_str) && et->defaultValue!=nullStr) {
|
|
if (syssetenv(et->name,et->defaultValue))
|
|
printf("Could not set NVRAM variable %s.\n", et->name);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**********
|
|
* resetenv
|
|
* --------
|
|
* QUESTION: Is it necessary to reset the EV in the
|
|
* env segment ??
|
|
*/
|
|
#undef REMOVEpersistentenv
|
|
#define REMOVEpersistentenv 1
|
|
#if !defined(REMOVEpersistentenv)
|
|
int
|
|
resetenv(void)
|
|
{
|
|
struct evTable* et;
|
|
|
|
/*
|
|
* Reconstruct all EV's from default table except for passwords.
|
|
*/
|
|
for (et = env_table; et->name; et++) {
|
|
if ((strcmp(et->name,PASSWD)==0) ||
|
|
(strcmp(et->name,NETPASSWD)==0))
|
|
continue;
|
|
delete_str(et->name, &environ_str);
|
|
if (et->defaultValue != nullStr)
|
|
if (syssetenv(et->name,et->defaultValue))
|
|
printf("Could not set NVRAM variable %s.\n", et->name);
|
|
}
|
|
|
|
/* Construct the boot EV's */
|
|
_init_bootenv();
|
|
}
|
|
#else
|
|
int
|
|
resetenv(void)
|
|
{
|
|
struct evTable* et;
|
|
char pwdbuf[20], netpwdbuf[20], *ptr, *cp;
|
|
int sts, strptr;
|
|
|
|
/*
|
|
* Find and copy the passwd environment variables to tmp buf.
|
|
*/
|
|
sts = 0;
|
|
if ((ptr = find_str(PASSWD, &environ_str)) != 0) {
|
|
if ((ptr = extractEVV(ptr)) != 0) strcpy(pwdbuf, ptr);
|
|
sts += 1;
|
|
}
|
|
if ((ptr = find_str(NETPASSWD, &environ_str)) != 0) {
|
|
if ((ptr = extractEVV(ptr)) != 0) strcpy(netpwdbuf, ptr);
|
|
sts += 2;
|
|
}
|
|
|
|
/*
|
|
* Clean the environ_str string.
|
|
*/
|
|
init_str(&environ_str);
|
|
for (strptr=0; strptr < STRINGBYTES; strptr++)
|
|
environ_str.strbuf[strptr] = 0;
|
|
|
|
/*
|
|
* Reconstruct all EV's from default table except for passwords.
|
|
*/
|
|
for (et = env_table; et->name; et++) {
|
|
if ((strcmp(et->name,PASSWD)==0) || (strcmp(et->name,NETPASSWD)==0))
|
|
continue;
|
|
if (et->defaultValue != nullStr)
|
|
if (syssetenv(et->name,et->defaultValue))
|
|
printf("Could not set NVRAM variable %s.\n", et->name);
|
|
}
|
|
|
|
/*
|
|
* Now taking care of the passwd stuff.
|
|
*/
|
|
if (sts >= 2) {
|
|
replace_str(NETPASSWD,netpwdbuf,&environ_str);
|
|
sts -= 2;
|
|
}
|
|
if (sts == 1) {
|
|
replace_str(PASSWD,pwdbuf,&environ_str);
|
|
sts -= 1;
|
|
}
|
|
|
|
/*
|
|
* Write the environment variable back to flash segment.
|
|
*/
|
|
if (rewriteFlashSegment(&envFlash,flashSeg,(long*)environ_str.strbuf))
|
|
printf("Error updating environment variables in FLASH\n");
|
|
|
|
/*
|
|
* Set EV values derived from other values or other state.
|
|
*/
|
|
init_consenv(0); /* Derives ConsoleIn/Out from console */
|
|
if (cp = cpu_get_freq_str(0)) /* Computes cpu frequency and sets EV */
|
|
syssetenv("cpufreq",cp); /* And set it in the evStr variable. */
|
|
cpu_get_eaddr_str(CPUeaddr); /* get the eaddr frome ds2506 */
|
|
syssetenv("eaddr",CPUeaddr); /* and set the eaddr ENV */
|
|
|
|
/* Construct the boot EV's */
|
|
_init_bootenv();
|
|
|
|
}
|
|
#endif
|
|
#undef REMOVEpersistentenv
|
|
|
|
/***************
|
|
* get_nvram_tab
|
|
* -------------
|
|
* Copy the env_table
|
|
*
|
|
* Used by kenel (via callback) to copy env_table from the PROM.
|
|
* Returns the number of bytes *NOT* copied so the kernel can detect
|
|
* if the table is longer than it thinks it is.
|
|
*
|
|
* Note: Poor name due to historical requirements.
|
|
*/
|
|
int
|
|
get_nvram_tab(char* addr, int size){
|
|
int totlen = size < sizeof(env_table) ? size : sizeof(env_table);
|
|
bcopy(env_table,addr,totlen);
|
|
return sizeof(env_table) - totlen;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Commands that deal with the environment variables,
|
|
* The old env_cmd.c from lib/libsc/cmd
|
|
*/
|
|
|
|
char *find_str(char *, struct string_list *);
|
|
int setenv (char *, char *);
|
|
|
|
extern struct string_list environ_str;
|
|
|
|
static char *readonly_errmsg = "Environment variable \"%s\" is"
|
|
" informative only and cannot be changed.\n";
|
|
|
|
static char *nvram_errmsg = "Error writing \"%s\" to the non-volatile RAM.\n"
|
|
"Variable \"%s\" is not saved in the permanent environment.\n";
|
|
|
|
/*
|
|
* setenv_cmd -- set environment variables
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
|
int
|
|
setenv_cmd(int argc, char **argv, char **bunk1, struct cmd_table *bunk2)
|
|
{
|
|
int rval, override;
|
|
char *var, *val;
|
|
ULONG fd;
|
|
|
|
/*
|
|
* usage should be
|
|
* setenv variable newvalue, or
|
|
* setenv -f variable newvalue
|
|
* setenv -p variable newvalue ("persistent" variable)
|
|
* (not supported on all machines)
|
|
*/
|
|
#ifdef VERBOSE_XXX
|
|
printf("setenv_cmd(%d,", argc);
|
|
{ int i;
|
|
for (i=1; i<argc; i++) printf("%s,",argv[i]);
|
|
printf(")\n");
|
|
}
|
|
#endif
|
|
if (argc == 4) {
|
|
if (strcmp (argv[1], "-f") == 0) {
|
|
override = 1;
|
|
var = argv[2];
|
|
val = argv[3];
|
|
}
|
|
else if (strcmp (argv[1], "-p") == 0) {
|
|
override = 2;
|
|
var = argv[2];
|
|
val = argv[3];
|
|
}
|
|
else
|
|
return(1);
|
|
}
|
|
else if (argc != 3)
|
|
return(1);
|
|
else {
|
|
override = 0;
|
|
var = argv[1];
|
|
val = argv[2];
|
|
}
|
|
|
|
rval = _setenv (var, val, override);
|
|
|
|
if (rval == EACCES) {
|
|
printf(readonly_errmsg, var);
|
|
return 0;
|
|
}
|
|
else if (rval != 0)
|
|
printf(nvram_errmsg, var, var);
|
|
|
|
/* other special environment variables
|
|
*/
|
|
if (!strcasecmp(var, "dbaud") &&
|
|
(Open((CHAR *)"serial(0)", OpenReadWrite, &fd) == ESUCCESS)) {
|
|
ioctl(fd, TIOCREOPEN, 0);
|
|
Close(fd);
|
|
}
|
|
|
|
if (!strcasecmp(var, "rbaud") &&
|
|
(Open((CHAR *)"serial(1)", OpenReadWrite, &fd) == ESUCCESS)) {
|
|
ioctl(fd, TIOCREOPEN, 0);
|
|
Close(fd);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* unsetenv_cmd -- unset environment variables
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
|
int
|
|
unsetenv_cmd(int argc, char **argv, char **bunk1, struct cmd_table *bunk2)
|
|
{
|
|
int rval;
|
|
|
|
if (argc != 2)
|
|
return(1);
|
|
|
|
if ((rval = setenv (argv[1], "")) != 0) {
|
|
if (rval == EACCES)
|
|
printf(readonly_errmsg, argv[1]);
|
|
else
|
|
printf(nvram_errmsg, argv[1], argv[1]);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
#define PASSWD "passwd_key"
|
|
#define NETPASSWD "netpasswd_key"
|
|
extern char* extractEVN(char*, char*);
|
|
|
|
/*
|
|
* printenv -- show an environment variable
|
|
*/
|
|
void
|
|
printenv(char *var)
|
|
{
|
|
char *cp;
|
|
|
|
if ((strcmp(var, PASSWD) != 0) && (strcmp(var, NETPASSWD) != 0x0))
|
|
if (cp = find_str(var, &environ_str))
|
|
printf("%s\n", cp);
|
|
}
|
|
|
|
/*
|
|
* printenv -- show environment variables
|
|
*/
|
|
|
|
/*ARGSUSED*/
|
|
int
|
|
printenv_cmd(int argc, char **argv, char **bunk1, struct cmd_table *bunk2)
|
|
{
|
|
int i;
|
|
char envName[64];
|
|
for (i=0; i<64; i++) envName[i]=0;
|
|
|
|
if (argc == 1) {
|
|
for (i = 0; i < environ_str.strcnt; i++) {
|
|
(void) extractEVN(environ_str.strptrs[i], envName);
|
|
if (strcmp(envName, PASSWD) != 0x0)
|
|
printf("%s\n", environ_str.strptrs[i]);
|
|
}
|
|
}
|
|
else while (--argc > 0)
|
|
printenv(*++argv);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/*
|
|
* NOTE: These two routines shouldn't be here.
|
|
*/
|
|
|
|
/******
|
|
* htoe
|
|
* ----
|
|
* Hex enet addr form (xx:xx:xx:xx:xx:xx) to raw enet addr
|
|
*/
|
|
char*
|
|
htoe(unsigned char* hex){
|
|
assert(0);
|
|
}
|
|
|
|
/******
|
|
* etoh
|
|
* ----
|
|
* Raw enet address to hex form.
|
|
*/
|
|
unsigned char*
|
|
etoh(char* enet){
|
|
assert(0);
|
|
}
|