/************************************************************************** * * 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 #include //#include #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); }