finally move buildroot-ng to trunk
[openwrt.git] / package / nvram / src / nvram_linux.c
1 /*
2  * NVRAM variable manipulation (Linux user mode half)
3  *
4  * Copyright 2004, Broadcom Corporation
5  * All Rights Reserved.
6  * 
7  * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8  * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9  * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10  * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11  *
12  * $Id$
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <errno.h>
19 #include <error.h>
20 #include <string.h>
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <sys/mman.h>
26
27 #include <typedefs.h>
28 #include <bcmnvram.h>
29 #include <nvram_convert.h>
30 #include <shutils.h>
31 #include <utils.h>
32
33 #define PATH_DEV_NVRAM "/dev/nvram"
34
35 /* Globals */
36 static int nvram_fd = -1;
37 static char *nvram_buf = NULL;
38 int check_action(void);
39 int file_to_buf(char *path, char *buf, int len);
40
41 int
42 nvram_init(void *unused)
43 {
44         if ((nvram_fd = open(PATH_DEV_NVRAM, O_RDWR)) < 0)
45                 goto err;
46
47         /* Map kernel string buffer into user space */
48         if ((nvram_buf = mmap(NULL, NVRAM_SPACE, PROT_READ, MAP_SHARED, nvram_fd, 0)) == MAP_FAILED) {
49                 close(nvram_fd);
50                 nvram_fd = -1;
51                 goto err;
52         }
53
54         return 0;
55
56  err:
57         perror(PATH_DEV_NVRAM);
58         return errno;
59 }
60
61 char *
62 nvram_get(const char *name)
63 {
64         size_t count = strlen(name) + 1;
65         char tmp[100], *value;
66         unsigned long *off = (unsigned long *) tmp;
67
68         if (nvram_fd < 0)
69                 if (nvram_init(NULL))
70                         return NULL;
71
72         if (count > sizeof(tmp)) {
73                 if (!(off = malloc(count)))
74                         return NULL;
75         }
76
77         /* Get offset into mmap() space */
78         strcpy((char *) off, name);
79
80         count = read(nvram_fd, off, count);
81
82         if (count == sizeof(unsigned long))
83                 value = &nvram_buf[*off];
84         else
85                 value = NULL;
86
87         if (count < 0)
88                 perror(PATH_DEV_NVRAM);
89
90         if (off != (unsigned long *) tmp)
91                 free(off);
92
93         return value;
94 }
95
96 int
97 nvram_getall(char *buf, int count)
98 {
99         int ret;
100
101         if (nvram_fd < 0)
102                 if ((ret = nvram_init(NULL)))
103                         return ret;
104
105         if (count == 0)
106                 return 0;
107
108         /* Get all variables */
109         *buf = '\0';
110
111         ret = read(nvram_fd, buf, count);
112
113         if (ret < 0)
114                 perror(PATH_DEV_NVRAM);
115
116         return (ret == count) ? 0 : ret;
117 }
118
119 static int
120 _nvram_set(const char *name, const char *value)
121 {
122         size_t count = strlen(name) + 1;
123         char tmp[100], *buf = tmp;
124         int ret;
125
126         if (nvram_fd < 0)
127                 if ((ret = nvram_init(NULL)))
128                         return ret;
129
130         /* Unset if value is NULL */
131         if (value)
132                 count += strlen(value) + 1;
133
134         if (count > sizeof(tmp)) {
135                 if (!(buf = malloc(count)))
136                         return -ENOMEM;
137         }
138
139         if (value)
140                 sprintf(buf, "%s=%s", name, value);
141         else
142                 strcpy(buf, name);
143
144         ret = write(nvram_fd, buf, count);
145
146         if (ret < 0)
147                 perror(PATH_DEV_NVRAM);
148
149         if (buf != tmp)
150                 free(buf);
151
152         return (ret == count) ? 0 : ret;
153 }
154
155 int
156 nvram_set(const char *name, const char *value)
157 {
158          extern struct nvram_convert nvram_converts[];
159          struct nvram_convert *v;
160          int ret;
161
162          ret = _nvram_set(name, value);
163
164          for(v = nvram_converts ; v->name ; v++) {
165                  if(!strcmp(v->name, name)){
166                          if(strcmp(v->wl0_name,""))      _nvram_set(v->wl0_name, value);
167                          if(strcmp(v->d11g_name,""))     _nvram_set(v->d11g_name, value);
168                  }
169          }
170
171          return ret;
172 }
173
174 int
175 nvram_unset(const char *name)
176 {
177         return _nvram_set(name, NULL);
178 }
179
180 int
181 nvram_commit(void)
182 {
183         int ret;
184         
185         cprintf("nvram_commit(): start\n");     
186         
187         if((check_action() == ACT_IDLE) || 
188            (check_action() == ACT_SW_RESTORE) || 
189            (check_action() == ACT_HW_RESTORE)){
190                 if (nvram_fd < 0)
191                         if ((ret = nvram_init(NULL)))
192                                 return ret;
193
194                 ret = ioctl(nvram_fd, NVRAM_MAGIC, NULL);
195
196                 if (ret < 0)
197                         perror(PATH_DEV_NVRAM);
198         
199                 cprintf("nvram_commit(): end\n");       
200         }
201         else
202                 cprintf("nvram_commit():  nothing to do...\n");
203
204         return ret;
205 }
206
207 int file2nvram(char *filename, char *varname) {
208    FILE *fp;
209    int c,count;
210    int i=0,j=0;
211    char mem[10000],buf[30000];
212
213    if ( !(fp=fopen(filename,"rb") ))
214         return 0;
215
216    count=fread(mem,1,sizeof(mem),fp);
217    fclose(fp);
218    for (j=0;j<count;j++) {
219         if  (i > sizeof(buf)-3 )
220                 break;
221         c=mem[j];
222         if (c >= 32 && c <= 126 && c != '\\' && c != '~')  {
223                 buf[i++]=(unsigned char) c;
224         } else if (c==0) {
225                 buf[i++]='~';
226         } else {
227                 buf[i++]='\\';
228                 sprintf(buf+i,"%02X",c);
229                 i+=2;
230         }
231    }
232    if (i==0) return 0;
233    buf[i]=0;
234    //fprintf(stderr,"================ > file2nvram %s = [%s] \n",varname,buf); 
235    nvram_set(varname,buf);
236    //nvram_commit(); //Barry adds for test
237 }
238
239 int nvram2file(char *varname, char *filename) {
240    FILE *fp;
241    int c,tmp;
242    int i=0,j=0;
243    char *buf;
244    char mem[10000];
245    
246    if ( !(fp=fopen(filename,"wb") ))
247         return 0;
248         
249    buf=strdup(nvram_safe_get(varname));
250    //fprintf(stderr,"=================> nvram2file %s = [%s] \n",varname,buf);
251    while (  buf[i] && j < sizeof(mem)-3 ) {
252         if (buf[i] == '\\')  {
253                 i++;
254                 tmp=buf[i+2];
255                 buf[i+2]=0;
256                 sscanf(buf+i,"%02X",&c);
257                 buf[i+2]=tmp;
258                 i+=2;
259                 mem[j]=c;j++;
260         } else if (buf[i] == '~') {
261                 mem[j]=0;j++;
262                 i++;
263         } else {
264                 mem[j]=buf[i];j++;
265                 i++;
266         }       
267    }
268    if (j<=0) return j;
269    j=fwrite(mem,1,j,fp);
270    fclose(fp);
271    free(buf);
272    return j;
273 }  
274
275 int
276 check_action(void)
277 {
278         char buf[80] = "";
279         
280         if(file_to_buf(ACTION_FILE, buf, sizeof(buf))){
281                 if(!strcmp(buf, "ACT_TFTP_UPGRADE")){
282                         cprintf("Upgrading from tftp now, quiet exit....\n");
283                         return ACT_TFTP_UPGRADE;
284                 }
285                 else if(!strcmp(buf, "ACT_WEBS_UPGRADE")){
286                         cprintf("Upgrading from web (https) now, quiet exit....\n");
287                         return ACT_WEBS_UPGRADE;
288                 }
289                 else if(!strcmp(buf, "ACT_WEB_UPGRADE")){
290                         cprintf("Upgrading from web (http) now, quiet exit....\n");
291                         return ACT_WEB_UPGRADE;
292                 }
293                 else if(!strcmp(buf, "ACT_SW_RESTORE")){
294                         cprintf("Receive restore command from web, quiet exit....\n");
295                         return ACT_SW_RESTORE;
296                 }
297                 else if(!strcmp(buf, "ACT_HW_RESTORE")){
298                         cprintf("Receive restore commond from resetbutton, quiet exit....\n");
299                         return ACT_HW_RESTORE;
300                 }
301         }
302         //fprintf(stderr, "Waiting for upgrading....\n");
303         return ACT_IDLE;
304 }
305
306 int
307 file_to_buf(char *path, char *buf, int len)
308 {
309         FILE *fp;
310
311         memset(buf, 0 , len);
312
313         if ((fp = fopen(path, "r"))) {
314                 fgets(buf, len, fp);
315                 fclose(fp);
316                 return 1;
317         }
318
319         return 0;
320 }