openwrt/target/linux/aruba-2.6/files/arch/mips/aruba/nvram/nvram434.c

393 lines
8.0 KiB
C

/**************************************************************************
*
* BRIEF MODULE DESCRIPTION
* nvram interface routines.
*
* Copyright 2004 IDT Inc. (rischelp@idt.com)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
**************************************************************************
* May 2004 rkt, neb
*
* Initial Release
*
*
*
**************************************************************************
*/
#include <linux/ctype.h>
#include <linux/string.h>
//#include <asm/ds1553rtc.h>
#include "nvram434.h"
#define NVRAM_BASE 0xbfff8000
extern void setenv (char *e, char *v, int rewrite);
extern void unsetenv (char *e);
extern void mapenv (int (*func)(char *, char *));
extern char *getenv (char *s);
extern void purgeenv(void);
static void nvram_initenv(void);
static unsigned char
nvram_getbyte(int offs)
{
return(*((unsigned char*)(NVRAM_BASE + offs)));
}
static void
nvram_setbyte(int offs, unsigned char val)
{
unsigned char* nvramDataPointer = (unsigned char*)(NVRAM_BASE + offs);
*nvramDataPointer = val;
}
/*
* BigEndian!
*/
static unsigned short
nvram_getshort(int offs)
{
return((nvram_getbyte(offs) << 8) | nvram_getbyte(offs + 1));
}
static void
nvram_setshort(int offs, unsigned short val)
{
nvram_setbyte(offs, (unsigned char)((val >> 8) & 0xff));
nvram_setbyte(offs + 1, (unsigned char)(val & 0xff));
}
#if 0
static unsigned int
nvram_getint(int offs)
{
unsigned int val;
val = nvram_getbyte(offs) << 24;
val |= nvram_getbyte(offs + 1) << 16;
val |= nvram_getbyte(offs + 2) << 8;
val |= nvram_getbyte(offs + 3);
return(val);
}
static void
nvram_setint(int offs, unsigned int val)
{
nvram_setbyte(offs, val >> 24);
nvram_setbyte(offs + 1, val >> 16);
nvram_setbyte(offs + 2, val >> 8);
nvram_setbyte(offs + 3, val);
}
#endif
/*
* calculate NVRAM checksum
*/
static unsigned short
nvram_calcsum(void)
{
unsigned short sum = NV_MAGIC;
int i;
for (i = ENV_BASE; i < ENV_TOP; i += 2)
sum += nvram_getshort(i);
return(sum);
}
/*
* update the nvram checksum
*/
static void
nvram_updatesum (void)
{
nvram_setshort(NVOFF_CSUM, nvram_calcsum());
}
/*
* test validity of nvram by checksumming it
*/
static int
nvram_isvalid(void)
{
static int is_valid;
if (is_valid)
return(1);
if (nvram_getshort(NVOFF_MAGIC) != NV_MAGIC) {
printk("nvram_isvalid FAILED\n");
//nvram_initenv();
}
is_valid = 1;
return(1);
}
/* return nvram address of environment string */
static int
nvram_matchenv(char *s)
{
int envsize, envp, n, i, varsize;
char *var;
envsize = nvram_getshort(NVOFF_ENVSIZE);
if (envsize > ENV_AVAIL)
return(0); /* sanity */
envp = ENV_BASE;
if ((n = strlen (s)) > 255)
return(0);
while (envsize > 0) {
varsize = nvram_getbyte(envp);
if (varsize == 0 || (envp + varsize) > ENV_TOP)
return(0); /* sanity */
for (i = envp + 1, var = s; i <= envp + n; i++, var++) {
char c1 = nvram_getbyte(i);
char c2 = *var;
if (islower(c1))
c1 = toupper(c1);
if (islower(c2))
c2 = toupper(c2);
if (c1 != c2)
break;
}
if (i > envp + n) { /* match so far */
if (n == varsize - 1) /* match on boolean */
return(envp);
if (nvram_getbyte(i) == '=') /* exact match on variable */
return(envp);
}
envsize -= varsize;
envp += varsize;
}
return(0);
}
static void nvram_initenv(void)
{
nvram_setshort(NVOFF_MAGIC, NV_MAGIC);
nvram_setshort(NVOFF_ENVSIZE, 0);
nvram_updatesum();
}
static void
nvram_delenv(char *s)
{
int nenvp, envp, envsize, nbytes;
envp = nvram_matchenv(s);
if (envp == 0)
return;
nenvp = envp + nvram_getbyte(envp);
envsize = nvram_getshort(NVOFF_ENVSIZE);
nbytes = envsize - (nenvp - ENV_BASE);
nvram_setshort(NVOFF_ENVSIZE, envsize - (nenvp - envp));
while (nbytes--) {
nvram_setbyte(envp, nvram_getbyte(nenvp));
envp++;
nenvp++;
}
nvram_updatesum();
}
static int
nvram_setenv(char *s, char *v)
{
int ns, nv, total;
int envp;
if (!nvram_isvalid())
return(-1);
nvram_delenv(s);
ns = strlen(s);
if (ns == 0)
return (-1);
if (v && *v) {
nv = strlen(v);
total = ns + nv + 2;
}
else {
nv = 0;
total = ns + 1;
}
if (total > 255 || total > ENV_AVAIL - nvram_getshort(NVOFF_ENVSIZE))
return(-1);
envp = ENV_BASE + nvram_getshort(NVOFF_ENVSIZE);
nvram_setbyte(envp, (unsigned char) total);
envp++;
while (ns--) {
nvram_setbyte(envp, *s);
envp++;
s++;
}
if (nv) {
nvram_setbyte(envp, '=');
envp++;
while (nv--) {
nvram_setbyte(envp, *v);
envp++;
v++;
}
}
nvram_setshort(NVOFF_ENVSIZE, envp-ENV_BASE);
nvram_updatesum();
return 0;
}
static char *
nvram_getenv(char *s)
{
static char buf[256]; /* FIXME: this cannot be static */
int envp, ns, nbytes, i;
if (!nvram_isvalid())
return "INVALID NVRAM"; //((char *)0);
envp = nvram_matchenv(s);
if (envp == 0)
return "NOT FOUND"; //((char *)0);
ns = strlen(s);
if (nvram_getbyte(envp) == ns + 1) /* boolean */
buf[0] = '\0';
else {
nbytes = nvram_getbyte(envp) - (ns + 2);
envp += ns + 2;
for (i = 0; i < nbytes; i++)
buf[i] = nvram_getbyte(envp++);
buf[i] = '\0';
}
return(buf);
}
static void
nvram_unsetenv(char *s)
{
if (!nvram_isvalid())
return;
nvram_delenv(s);
}
/*
* apply func to each string in environment
*/
static void
nvram_mapenv(int (*func)(char *, char *))
{
int envsize, envp, n, i, seeneql;
char name[256], value[256];
char c, *s;
if (!nvram_isvalid())
return;
envsize = nvram_getshort(NVOFF_ENVSIZE);
envp = ENV_BASE;
while (envsize > 0) {
value[0] = '\0';
seeneql = 0;
s = name;
n = nvram_getbyte(envp);
for (i = envp + 1; i < envp + n; i++) {
c = nvram_getbyte(i);
if ((c == '=') && !seeneql) {
*s = '\0';
s = value;
seeneql = 1;
continue;
}
*s++ = c;
}
*s = '\0';
(*func)(name, value);
envsize -= n;
envp += n;
}
}
#if 0
static unsigned int
digit(char c)
{
if ('0' <= c && c <= '9')
return (c - '0');
if ('A' <= c && c <= 'Z')
return (10 + c - 'A');
if ('a' <= c && c <= 'z')
return (10 + c - 'a');
return (~0);
}
#endif
/*
* Wrappers to allow 'special' environment variables to get processed
*/
void
setenv(char *e, char *v, int rewrite)
{
if (nvram_getenv(e) && !rewrite)
return;
nvram_setenv(e, v);
}
char *
getenv(char *e)
{
return(nvram_getenv(e));
}
void
unsetenv(char *e)
{
nvram_unsetenv(e);
}
void
purgeenv()
{
int i;
unsigned char* nvramDataPointer = (unsigned char*)(NVRAM_BASE);
for (i = ENV_BASE; i < ENV_TOP; i++)
*nvramDataPointer++ = 0;
nvram_setshort(NVOFF_MAGIC, NV_MAGIC);
nvram_setshort(NVOFF_ENVSIZE, 0);
nvram_setshort(NVOFF_CSUM, NV_MAGIC);
}
void
mapenv(int (*func)(char *, char *))
{
nvram_mapenv(func);
}