2 * NVRAM variable manipulation (Linux user mode half)
4 * Copyright 2005, Broadcom Corporation
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.
12 * $Id: nvram_linux.c,v 1.18 2005/05/16 12:35:03 honor Exp $
21 #include <sys/ioctl.h>
22 #include <sys/types.h>
29 #include <nvram_convert.h>
34 #define PATH_DEV_NVRAM "/dev/nvram"
37 static int nvram_fd
= -1;
38 static char *nvram_buf
= NULL
;
40 int nvram_init(void *unused
)
42 if ((nvram_fd
= open(PATH_DEV_NVRAM
, O_RDWR
)) >= 0) {
43 /* Map kernel string buffer into user space */
44 if ((nvram_buf
= mmap(NULL
, NVRAM_SPACE
, PROT_READ
, MAP_SHARED
, nvram_fd
, 0)) != MAP_FAILED
) {
45 fcntl(nvram_fd
, F_SETFD
, FD_CLOEXEC
); // zzz
51 perror(PATH_DEV_NVRAM
);
55 char *nvram_get(const char *name
)
59 size_t count
= strlen(name
) + 1;
60 unsigned long *off
= (unsigned long *)tmp
;
63 if (nvram_init(NULL
) != 0) return NULL
;
66 if (count
> sizeof(tmp
)) {
67 if ((off
= malloc(count
)) == NULL
) return NULL
;
70 /* Get offset into mmap() space */
71 strcpy((char *) off
, name
);
72 count
= read(nvram_fd
, off
, count
);
74 if (count
== sizeof(*off
)) {
75 value
= &nvram_buf
[*off
];
79 if (count
< 0) perror(PATH_DEV_NVRAM
);
82 if (off
!= (unsigned long *)tmp
) free(off
);
86 int nvram_getall(char *buf
, int count
)
90 if (count
<= 0) return 0;
94 if ((r
= nvram_init(NULL
)) != 0) return r
;
96 r
= read(nvram_fd
, buf
, count
);
97 if (r
< 0) perror(PATH_DEV_NVRAM
);
98 return (r
== count
) ? 0 : r
;
101 static int _nvram_set(const char *name
, const char *value
)
103 size_t count
= strlen(name
) + 1;
109 if ((ret
= nvram_init(NULL
)) != 0) return ret
;
112 /* Unset if value is NULL */
113 if (value
) count
+= strlen(value
) + 1;
115 if (count
> sizeof(tmp
)) {
116 if ((buf
= malloc(count
)) == NULL
) return -ENOMEM
;
120 sprintf(buf
, "%s=%s", name
, value
);
126 ret
= write(nvram_fd
, buf
, count
);
127 if (ret
< 0) perror(PATH_DEV_NVRAM
);
129 if (buf
!= tmp
) free(buf
);
131 return (ret
== count
) ? 0 : ret
;
134 int nvram_set(const char *name
, const char *value
)
136 struct nvram_convert
*v
;
138 for (v
= nvram_converts
; v
->name
; v
++) {
139 if (!strcmp(v
->name
, name
)) {
140 _nvram_set(v
->wl0_name
, value
);
145 if (strncmp(name
, "wl_", 3) == 0) {
148 if (strlen(name
) < 32) {
149 sprintf(wl0
, "wl0_%s", name
+ 3);
150 _nvram_set(wl0
, value
);
154 return _nvram_set(name
, value
);
157 int nvram_unset(const char *name
)
159 return _nvram_set(name
, NULL
);
162 int nvram_commit(void)
166 if (wait_action_idle(10)) {
168 if ((r
= nvram_init(NULL
)) != 0) return r
;
170 set_action(ACT_NVRAM_COMMIT
);
171 // nvram_unset("dirty");
172 r
= ioctl(nvram_fd
, NVRAM_MAGIC
, NULL
);
173 set_action(ACT_IDLE
);
175 perror(PATH_DEV_NVRAM
);
176 cprintf("commit: error\n");
180 cprintf("commit: system busy\n");
187 * Write a file to an NVRAM variable.
188 * @param name name of variable to get
189 * @param filenname name of file to write
190 * @return return code
192 * Preserve mode (permissions) of the file.
193 * Create the output directory.
196 #define MAGICNUM 0x12161770 /* Ludwig van Beethoven's birthdate. */
197 int nvram_file2nvram(const char *varname
, const char *filename
)
203 unsigned char mem
[MAX_FS
], buf
[3 * MAX_FS
];
205 if ( !(fp
=fopen(filename
,"rb") )) {
210 stat(filename
, &stbuf
);
211 *((mode_t
*)mem
) = stbuf
.st_mode
;
212 *((mode_t
*)mem
+1) = MAGICNUM
;
214 count
=fread(mem
+ 2*sizeof(mode_t
), 1, sizeof(mem
) - 2*sizeof(mode_t
), fp
);
217 fprintf(stderr
, "File too big.\n");
221 count
+= 2*sizeof(mode_t
);
222 for (j
= 0; j
< count
; j
++) {
223 if (i
> sizeof(buf
)-3 )
226 if (c
>= 32 && c
<= 126 && c
!= '\\' && c
!= '~') {
227 buf
[i
++]=(unsigned char) c
;
232 sprintf(buf
+i
,"%02X",c
);
237 nvram_set(varname
,buf
);
242 * Get the value of an NVRAM variable and write it to a file.
243 * It must have been written with nvram_file2nvram.
244 * Directory path(s) are created, and permissions are preserved.
245 * @param name name of variable to get
246 * @param filenname name of file to write
247 * @return return code
249 int nvram_nvram2file(const char *varname
, const char *filename
)
255 unsigned char mem
[MAX_FS
], buf
[3 * MAX_FS
];
257 cp
= nvram_get(varname
);
259 printf("Key does not exist: %s\n", varname
);
263 while (buf
[i
] && j
< sizeof(mem
)-3 ) {
264 if (buf
[i
] == '\\') {
268 sscanf(buf
+i
,"%02X",&c
);
272 } else if (buf
[i
] == '~') {
282 if (*((mode_t
*)mem
+1) != MAGICNUM
) {
283 printf("Error: '%s' not created by nvram setfile.\n", varname
);
287 /* Create the directories to the path, as necessary. */
288 strcpy(buf
, filename
);
289 cp
= strrchr(buf
, '/');
290 if (cp
&& cp
> buf
) {
292 eval("mkdir", "-m", "0777", "-p", buf
);
295 if ( (fnum
=open(filename
, O_WRONLY
| O_CREAT
| O_TRUNC
, *((mode_t
*)mem
))) < 0) {
296 printf("failed. errno: %d\n", errno
);
300 i
= write(fnum
, mem
+ 2*sizeof(mode_t
), j
- 2* sizeof(mode_t
));
301 if (i
!= j
- 2* sizeof(mode_t
))
304 return (i
!= (j
- 2* sizeof(mode_t
)));