add added files
[bcm963xx.git] / userapps / broadcom / nvram / nvram_shared.c
diff --git a/userapps/broadcom/nvram/nvram_shared.c b/userapps/broadcom/nvram/nvram_shared.c
new file mode 100755 (executable)
index 0000000..708113a
--- /dev/null
@@ -0,0 +1,842 @@
+/*
+ * NVRAM variable manipulation (common)
+ *
+ * $Copyright Open Broadcom Corporation$
+ * 
+ * NVRAM emulation interface
+ *
+ * $Id:$
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <typedefs.h>
+#include <bcmendian.h>
+#include <bcmnvram.h>
+#include <bcmutils.h>
+
+/* for file locking */
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#define LOCK_FILE      "/var/nvram.lock"
+#define MAX_LOCK_WAIT  10
+
+/* for mmap */
+#include <sys/mman.h>
+#define NVRAM_FILE     "/var/nvram"
+
+/* internal structure */
+struct nvram_header nv_header = { 0x48534C46, 0x14, 0x52565344, 0, 0xffffffff };
+static struct nvram_tuple * nvram_hash[32] = { NULL };
+static struct nvram_tuple * nvram_dead = NULL;
+static struct nvram_tuple * nvram_deleted = NULL;
+
+/* declaration */
+char * _nvram_get(const char *name);
+int _nvram_set(const char *name, const char *value);
+int _nvram_unset(const char *name);
+int _nvram_getall(char *buf, int count);
+int _nvram_commit(struct nvram_header *header);
+int _nvram_init(void);
+void _nvram_exit(void);
+int nvram_getall(char *buf, int count);
+int _nvram_refresh(const char *name, const char *value);
+
+static int _lock();
+static int _unlock();
+static int _nvram_lock();
+static int _nvram_unlock();
+static void* _nvram_mmap_alloc(int size);
+static void* _nvram_mmap_free(void *va, int size);
+
+#define _MALLOC_(x)            calloc(x, sizeof(char))
+#define _MFREE_(buf, size)     free(buf)
+
+#define _NVRAM_MALLOC_(x)       _nvram_mmap_alloc(x)
+#define _NVRAM_MFREE_(buf, size) _nvram_mmap_free(buf,size)
+
+static int nvram_inited=0;
+
+#define DBG_NVRAM_SET          0x00000001
+#define DBG_NVRAM_GET          0x00000002
+#define DBG_NVRAM_GETALL       0x00000004
+#define DBG_NVRAM_UNSET        0x00000008
+#define DBG_NVRAM_COMMIT       0x00000010
+#define DBG_NVRAM_UPDATE       0x00000020
+#define DBG_NVRAM_INFO         0x00000040
+#define DBG_NVRAM_ERROR        0x00000080
+
+
+#ifdef BCMDBG
+#define DBG_SET(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_SET) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#define DBG_GET(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_GET) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#define DBG_GETALL(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_GETALL) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#define DBG_UNSET(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_UNSET) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#define DBG_COMMIT(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_COMMIT) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#define DBG_UPDATE(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_UPDATE) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#define DBG_INFO(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_INFO) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#define DBG_ERROR(fmt, arg...) \
+        do { if (debug_nvram_level & DBG_NVRAM_ERROR) \
+                printf("%s: "fmt , __FUNCTION__ , ##arg); } while(0)
+
+#else
+#define DBG_SET(fmt, arg...)
+#define DBG_GET(fmt, arg...)
+#define DBG_GETALL(fmt, arg...)
+#define DBG_UNSET(fmt, arg...)
+#define DBG_COMMIT(fmt, arg...)
+#define DBG_UPDATE(fmt, arg...)
+#define DBG_INFO(fmt, arg...)
+#define DBG_ERROR(fmt, arg...)
+#endif
+
+static int debug_nvram_level = DBG_NVRAM_ERROR;
+
+static int _lock()
+{
+       int fd;
+       fd = open(LOCK_FILE,O_WRONLY|O_CREAT|O_EXCL,0644);
+       if (fd < 0 && errno == EEXIST) {
+               DBG_INFO("%s is already locked\n",LOCK_FILE);
+               return 0;               
+       } else if (fd < 0){
+               DBG_ERROR("unexpected error checking lock");                    
+               return 0;
+       }
+       DBG_INFO(" nvram : %s created\n",LOCK_FILE);
+       close(fd);
+       return 1;
+}
+
+static int _unlock()
+{
+       if (unlink(LOCK_FILE) < 0) {
+               DBG_ERROR("cannot remove lock file");
+               return 0;
+       }               
+       DBG_INFO(" nvram : %s deleted\n",LOCK_FILE);
+       return 1;
+}
+
+static int _nvram_lock()
+{
+       int i=0;
+       while (!_lock() && (i++ < MAX_LOCK_WAIT)) {             
+               usleep(500000); 
+       }       
+       if(i >= MAX_LOCK_WAIT)
+               return 0;       
+       else
+               return 1;       
+}
+static int _nvram_unlock()
+{
+       int i=0;
+       while (!_unlock() && (i++ < MAX_LOCK_WAIT)) {           
+               usleep(500000); 
+       }       
+       if(i > MAX_LOCK_WAIT)
+               return 0;       
+       else
+               return 1;       
+}
+
+
+static void* _nvram_mmap_alloc(int size)
+{
+       int fd;
+       void *va=NULL;
+               
+       if((fd = open(NVRAM_FILE, O_CREAT|O_SYNC|O_RDWR, 0644)) < 0) {
+               DBG_ERROR(" nvram: file open error");
+               return 0;       
+       }
+       
+       ftruncate(fd,size);     
+       
+       va = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, fd, 0);
+       if(va == ((caddr_t) - 1)) {
+               DBG_ERROR(" nvram: mmap errorr");
+               return 0;
+       }
+       DBG_INFO("nvram: va obtained=0x%x\n",(uint32)va);
+       close(fd);      
+       return va;
+       
+}
+
+static void* _nvram_mmap_free(void *va, int size)
+{
+       int fd;
+               
+       if((fd = open(NVRAM_FILE, O_SYNC|O_RDWR, 0644)) < 0) {
+               perror(" nvram: _nvram_mmap_free file open error");
+               return 0;       
+       }       
+       /*flush*/
+       DBG_INFO("close file with %d bytes\n",((struct nvram_header*)va)->len);
+       ftruncate(fd,((struct nvram_header*)va)->len);
+       msync((caddr_t)va, ((struct nvram_header*)va)->len,MS_SYNC);    
+       munmap((caddr_t)va, size);      
+       close(fd);
+}
+
+
+
+static int
+_nvram_read(void *buf)
+{
+        uint32 *src, *dst;
+        uint i;
+       int ret=0;
+       
+        if (!nv_header.magic)
+                return -19; /* -ENODEV */
+
+        src = (uint32 *) &nv_header;
+        dst = (uint32 *) buf;
+
+       if(((struct nvram_header *)dst)->magic == NVRAM_MAGIC && ((struct nvram_header *)dst)->len != sizeof(struct nvram_header)){
+               /* nvram exists */
+               DBG_INFO("nvram exist, len=%d\n",nv_header.len);
+               nv_header.len = ((struct nvram_header *)dst)->len;
+               if(nv_header.config_refresh != ((struct nvram_header *)dst)->config_refresh){
+                       DBG_INFO("revision changed=%d\n",nv_header.config_refresh);
+                       ret = 0; //1; /*need merge*/
+               }else{
+                       DBG_INFO("revision NOT changed=%d\n",nv_header.config_refresh);
+                       ret = 0; //2; /*no change*/
+               }               
+       }else {
+               /* nvram is empty */
+               DBG_INFO("nvram empty\n");
+               nv_header.len = sizeof(struct nvram_header);
+               nv_header.config_refresh = 0;
+               for (i = 0; i < sizeof(struct nvram_header); i += 4)
+                       *dst++ = *src++;
+                       
+                       /* PR2620 WAR: Read data bytes as words */
+               for (; i < nv_header.len && i < NVRAM_SPACE; i += 4) {
+                       *dst++ = ltoh32(*src++);
+               }        
+               ret = 0;
+       }
+
+        return ret;
+}
+
+static struct nvram_tuple *
+_nvram_realloc(struct nvram_tuple *t, const char *name, const char *value)
+{
+        if (!(t = _MALLOC_(sizeof(struct nvram_tuple) + strlen(name) + 1 + strlen(value) + 1))) {
+               DBG_ERROR ( "malloc failed\n");
+                return NULL;
+                                       
+       }
+       
+        /* Copy name */
+        t->name = (char *) &t[1];
+        strcpy(t->name, name);
+
+        /* Copy value */
+        t->value = t->name + strlen(name) + 1;
+        strcpy(t->value, value);
+
+        return t;
+}
+
+static void _nvram_free(struct nvram_tuple *t)
+{
+       if (t) {
+               _MFREE_(t, sizeof(struct nvram_tuple) + strlen(t->name) + 1 + strlen(t->value) + 1);
+       }
+}
+
+/* Free all tuples. Should be locked. */
+static void
+nvram_free(void)
+{
+       uint i;
+       struct nvram_tuple *t, *next;
+
+       DBG_INFO("nvram_free:hashtable, ");
+       /* Free hash table */
+       for (i = 0; i < ARRAYSIZE(nvram_hash); i++) {
+               for (t = nvram_hash[i]; t; t = next) {
+                       next = t->next;
+                       _nvram_free(t);
+               }
+               nvram_hash[i] = NULL;
+       }
+
+       DBG_INFO("nvram_free: deadtable, ");
+       /* Free dead table */
+       for (t = nvram_dead; t; t = next) {
+               next = t->next;
+               _nvram_free(t);
+       }
+       nvram_dead = NULL;
+
+       DBG_INFO("nvram_free:deletedtable, ");
+       
+       /* Free deleted table */
+       for (t = nvram_deleted; t; t = next) {
+               next = t->next;
+               _nvram_free(t);
+       }
+       nvram_deleted = NULL;
+
+
+       /* Indicate to per-port code that all tuples have been freed */
+       _nvram_free(NULL);
+       DBG_INFO("nvram_free(4)");
+}
+
+/* String hash */
+static INLINE uint
+hash(const char *s)
+{
+       uint hash = 0;
+
+       while (*s) {
+               hash = 31 * hash + *s++;
+       }
+
+       return hash;
+}
+
+/* (Re)initialize the hash table. */
+static int
+nvram_rehash(struct nvram_header *header)
+{
+       char *name, *value, *end, *eq;
+
+       /* (Re)initialize hash table */
+       nvram_free();
+
+       /* Parse and set "name=value\0 ... \0\0" */
+       name = (char *) &header[1];
+       end = (char *) header + NVRAM_SPACE - 2;
+       end[0] = end[1] = '\0';
+       for (; *name; name = value + strlen(value) + 1) {
+               if (!(eq = strchr(name, '=')))
+                       break;
+               *eq = '\0';
+               value = eq + 1;
+               _nvram_set(name, value);
+               *eq = '=';
+       }
+
+       return 0;
+}
+
+/* (Re) merge the hash table. */
+/* For conflict items, use the one in hash table, not from nvram. */
+static int
+_nvram_update(struct nvram_header *header)
+{
+       char *name, *value, *end, *eq;
+       struct nvram_tuple *t, *next;
+       int merge=0;
+
+       if( !nvram_dead && nv_header.config_refresh ==  header->config_refresh){
+               /*nothing changed*/
+               DBG_UPDATE("nothing to update revision=%d\n", nv_header.config_refresh);
+               return 0;       
+       }
+       nv_header.config_refresh = header->config_refresh; // sync revision number
+
+       /* Parse and set "name=value\0 ... \0\0" */
+       name = (char *) &header[1];
+       end = (char *) header + NVRAM_SPACE - 2;
+       end[0] = end[1] = '\0';
+       for (; *name; name = value + strlen(value) + 1) {
+               if (!(eq = strchr(name, '=')))
+                       break;
+               merge=1;                
+               *eq = '\0';
+               value= eq + 1;
+               if(nvram_dead) {                
+                       /*check if this item is in dead table, means being changed*/
+                       for (t=nvram_dead; t; t=next) {
+                               next=t->next;
+                               if(!strcmp(t->name,name)){                                      
+                                       merge = 0;
+                                       break; /*don't merge this one*/                                 
+                               }               
+                       }       
+               } 
+
+               if(nvram_deleted) {             
+                       /*check if this item is in deleted table, means to not use*/
+                       for (t=nvram_deleted; t; t=next) {
+                               next=t->next;
+                               if(!strcmp(t->name,name)){                                      
+                                       merge = 0;
+                                       break; /*don't merge this one*/                                 
+                               }               
+                       }       
+               } 
+               
+               if(merge) {                     
+                       if(_nvram_get(name)){
+                               _nvram_refresh(name, value);
+                               DBG_UPDATE("%s updated =%s \n",name,value);                                                                                             
+                       } else {
+                               _nvram_set(name, value);
+                               DBG_UPDATE("%s merged =%s \n",name,value);
+                       }
+               }
+               *eq = '=';                      
+       }
+       return 0;
+}
+
+/* Get the value of an NVRAM variable. */
+char *
+_nvram_get(const char *name)
+{
+       uint i;
+       struct nvram_tuple *t, *next;
+       char *value;
+
+       if (!name)
+               return NULL;
+
+       if(nvram_deleted) {             
+               /*return NULL if unset */
+               for (t=nvram_deleted; t; t=next) {
+                       next = t->next;
+                       if(!strcmp(t->name, name)){                                     
+                               return NULL;
+                       }               
+               }       
+       }         
+
+       /* Hash the name */
+       i = hash(name) % ARRAYSIZE(nvram_hash);
+
+       /* Find the associated tuple in the hash table */
+       for (t = nvram_hash[i]; t && strcmp(t->name, name); t = t->next) {
+               ;
+       }
+
+       value = t ? t->value : NULL;
+
+       return value;
+}
+
+
+
+/* Refresh value of an NVRAM variable. */
+int
+_nvram_refresh(const char *name, const char *value)
+{
+       uint i;
+       struct nvram_tuple *t, *u, **prev;
+
+       /* Hash the name */
+       i = hash(name) % ARRAYSIZE(nvram_hash);
+
+       /* Find the associated tuple in the hash table */
+       for (prev = &nvram_hash[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev) {
+               ;
+       }
+
+       /* (Re)allocate tuple */
+       if (!(u = _nvram_realloc(t, name, value))) {
+               DBG_ERROR("no memory\n");
+               return -12; /* -ENOMEM */
+       }
+       
+       /* Value reallocated */
+       if (t && t == u) {
+               DBG_INFO(" >> t==u set <<\n"); //why?
+               return 0;
+        }
+
+       // release old tuple
+       if (t) {
+               DBG_INFO("========release %s=%s =======\n", t->name, t->value);
+               *prev = t->next;
+               _nvram_free(t);
+       }
+
+       /* Add new tuple to the hash table */
+       u->next = nvram_hash[i];
+       nvram_hash[i] = u;
+
+       return 0;
+}
+
+
+/* Get the value of an NVRAM variable. */
+int
+_nvram_set(const char *name, const char *value)
+{
+       uint i;
+       struct nvram_tuple *t, *u, **prev;
+
+       /* Hash the name */
+       i = hash(name) % ARRAYSIZE(nvram_hash);
+
+       /* Find the associated tuple in the hash table */
+       for (prev = &nvram_hash[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev) {
+               ;
+       }
+
+       /* (Re)allocate tuple */
+       if (!(u = _nvram_realloc(t, name, value))) {
+               DBG_ERROR("no memory\n");
+               return -12; /* -ENOMEM */
+       }
+       
+       /* Value reallocated */
+       if (t && t == u) {
+               DBG_INFO(" >> t==u set <<\n"); //why?
+               return 0;
+        }
+
+       // Move old tuple to the dead table 
+       if (t) {
+               DBG_INFO("========nvram set move (%s=%s) to  dead =======\n", t->name, t->value);
+               *prev = t->next;
+               t->next = nvram_dead;
+               nvram_dead = t;
+       }
+
+       /* Add new tuple to the hash table */
+       u->next = nvram_hash[i];
+       nvram_hash[i] = u;
+
+       return 0;
+}
+
+/* Unset the value of an NVRAM variable. */
+int
+_nvram_unset(const char *name)
+{
+       uint i;
+       struct nvram_tuple *t, *u, **prev;
+
+       if (!name)
+               return 0;
+
+       /* Hash the name */
+       i = hash(name) % ARRAYSIZE(nvram_hash);
+
+       /* Find the associated tuple in the hash table */
+       for (prev = &nvram_hash[i], t = *prev; t && strcmp(t->name, name); prev = &t->next, t = *prev) {
+               ;
+       }
+
+       /* Move it to the deleted table */
+       if (t) {
+               *prev = t->next;
+               t->next = nvram_deleted;
+               nvram_deleted = t;
+       }else{
+               /* create a touple and move it to deleted table*/
+               if (!(u = _nvram_realloc(t, name, " "))) {
+                       DBG_ERROR("no memory\n");
+                       return -12; /* -ENOMEM */
+               }
+       
+               u->next = nvram_deleted;
+               nvram_deleted = u;
+       }
+
+       return 0;
+}
+
+/* Get all NVRAM variables. */
+int
+_nvram_getall(char *buf, int count)
+{
+       uint i;
+       struct nvram_tuple *t;
+       int len = 0;
+       
+       bzero(buf, count);
+
+       /* Write name=value\0 ... \0\0 */
+       for (i = 0; i < ARRAYSIZE(nvram_hash); i++) {
+               for (t = nvram_hash[i]; t; t = t->next) {
+                       if ((count - len) > (strlen(t->name) + 1 + strlen(t->value) + 1))
+                               len += sprintf(buf + len, "%s=%s", t->name, t->value) + 1;
+                       else
+                               break;
+               }
+       }
+
+       return 0;
+}
+
+/* Regenerate NVRAM. */
+int
+_nvram_commit(struct nvram_header *header)
+{
+       char *ptr, *end;
+       int i;
+       struct nvram_tuple *t;
+               
+       /* Regenerate header */
+       header->magic = NVRAM_MAGIC;
+
+       /* Clear data area */
+       ptr = (char *) header + sizeof(struct nvram_header);
+       bzero(ptr, NVRAM_SPACE - sizeof(struct nvram_header));
+
+       /* Leave space for a double NUL at the end */
+       end = (char *) header + NVRAM_SPACE - 2;
+
+       /* Write out all tuples */
+       for (i = 0; i < ARRAYSIZE(nvram_hash); i++) {
+               for (t = nvram_hash[i]; t; t = t->next) {
+                       if ((ptr + strlen(t->name) + 1 + strlen(t->value) + 1) > end)
+                               break;
+                       ptr += sprintf(ptr, "%s=%s", t->name, t->value) + 1;
+                       DBG_COMMIT("_nvram_commit writing %s=%s \n", t->name, t->value);
+               }
+       }
+
+       /* End with a double NUL */
+       ptr += 2;
+
+       /* Set new length */
+       header->len = ROUNDUP(ptr - (char *) header, 4);
+       
+       /* Set new revision, steal config_refresh for indication  */
+       header->config_refresh=(++nv_header.config_refresh);
+       DBG_COMMIT("new revision=%d\n",header->config_refresh);
+       /* Reinitialize hash table */                           
+       i=nvram_rehash(header);
+
+       return i;
+       
+}
+
+/* Initialize hash table. */
+int
+_nvram_init(void)
+{
+       struct nvram_header *header;
+       int ret;
+
+       if (!(header = (struct nvram_header *) _NVRAM_MALLOC_(NVRAM_SPACE))) {
+               DBG_ERROR("nvram_init: out of memory\n");
+
+               return -12; /* -ENOMEM */
+       }
+
+
+       if ((ret = _nvram_read(header)) == 0 &&
+           header->magic == NVRAM_MAGIC){
+               /*empty*/
+               nvram_rehash(header);
+       }
+       
+#if 0          
+       } else if (ret == 1 &&
+           header->magic == NVRAM_MAGIC){
+               /*revision made by others*/
+               nvram_merge(header);
+       } else if (ret == 2 &&
+           header->magic == NVRAM_MAGIC && nvram_dead){
+               /*internal made by self*/
+               nvram_merge(header);
+       } else if (ret == 2 &&
+           header->magic == NVRAM_MAGIC && nvram_dead==NULL){
+               /*no internal change, no external change*/
+               nvram_rehash(header);
+       }
+#endif         
+       _NVRAM_MFREE_(header, NVRAM_SPACE);
+
+
+       nvram_inited=1;
+       return ret;
+}
+
+/* Free hash table. */
+void
+_nvram_exit(void)
+{
+       nvram_free();
+}
+
+int
+nvram_commit(void)
+{
+        struct nvram_header *header;
+        int ret;
+        uint32 *src, *dst;
+        uint i;
+        
+       DBG_COMMIT("==>nvram_commit\n");
+       
+       if(!_nvram_lock())
+               goto fail_commit;
+
+       if(!nvram_inited){
+               _nvram_init();
+       }
+
+        if (!(header = (struct nvram_header *) _NVRAM_MALLOC_(NVRAM_SPACE))) {
+                DBG_ERROR("nvram_commit: out of memory\n");
+                ret= -12; /* -ENOMEM */
+                goto fail_commit;
+        }
+                
+        _nvram_update(header);
+        
+
+        /* Regenerate NVRAM */
+        ret = _nvram_commit(header);
+        if (ret)
+                goto done_commit;
+
+        src = (uint32 *) &header[1];
+        dst = src;
+
+        /* PR2620 WAR: Write data bytes as words */
+        for (i = sizeof(struct nvram_header); i < header->len && i < NVRAM_SPACE; i += 4)
+                *dst++ = htol32(*src++);
+
+ done_commit:
+        _NVRAM_MFREE_(header, NVRAM_SPACE);
+ fail_commit:       
+       _nvram_unlock();
+       
+       DBG_COMMIT("<==nvram_commit\n");
+               
+        return ret;
+}
+
+char *
+nvram_get(const char *name)
+{
+       char *ret=NULL;
+       struct nvram_header *header;
+               
+       DBG_GET("==>nvram_get\n");
+       
+       if(!_nvram_lock())
+               goto fail_get;
+       
+       if(!nvram_inited){
+               _nvram_init();
+               
+       } else {
+
+               if (!(header = (struct nvram_header *) _NVRAM_MALLOC_(NVRAM_SPACE))) {
+                       DBG_ERROR("nvram_commit: out of memory\n");
+                       goto fail_get;
+               }
+                
+               _nvram_update(header);  
+
+               _NVRAM_MFREE_(header, NVRAM_SPACE);
+               
+        }
+        
+       ret=_nvram_get(name);
+
+       _nvram_unlock();
+               
+       DBG_GET("%s=%s\n",name, ret);
+       DBG_GET("<==nvram_get\n");
+       
+       return ret;     
+ fail_get:             
+       return (char*)NULL;
+}
+
+int
+nvram_set(const char *name, const char *value)
+{
+       int ret=0;
+       DBG_SET("==>nvram_set\n");
+       if(!_nvram_lock())
+               goto fail_set;
+               
+       if(!nvram_inited){
+               _nvram_init();
+       }       
+       DBG_SET("name=%s = %s\n",name, value);
+       ret=_nvram_set(name,value);//_nvram_set_and_mark(name,value); 
+       _nvram_unlock();
+               
+       DBG_SET("<==nvram_set\n");      
+       return ret;
+fail_set:
+       return -1;
+       
+}
+
+int
+nvram_getall(char *buf, int count)
+{
+       int ret;
+       DBG_GETALL("==>nvram_getall\n");
+       if(!_nvram_lock())
+               goto fail_getall;
+               
+       if(!nvram_inited){
+               _nvram_init();
+       }       
+       ret=_nvram_getall(buf, count);
+       
+       _nvram_unlock();
+       
+       DBG_GETALL("<==nvram_getall\n");        
+       return ret;
+       
+fail_getall:
+       return -1;      
+}
+
+int
+nvram_unset(const char *name)
+{
+       int ret;
+               
+       DBG_UNSET("==>nvram_unset\n");
+       if(!_nvram_lock())
+               goto fail_unset;
+               
+       if(!nvram_inited){
+               _nvram_init();
+       }       
+
+       ret=_nvram_unset(name);
+       _nvram_unlock();
+               
+       DBG_UNSET("<==nvram_unset\n");
+       return ret;
+fail_unset:
+       return -1;      
+}
\ No newline at end of file