finally move buildroot-ng to trunk
[openwrt/staging/florian.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 }