K2.6 patches and update.
[tomato.git] / release / src-rt / linux / linux-2.6 / arch / mips / brcm-boards / bcm947xx / nvram_linux.c
blob2965f1972dc454bfcc6170d26cd4ef095f00918a
1 /*
2 * NVRAM variable manipulation (Linux kernel half)
4 * All Rights Reserved.
5 *
6 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
7 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
8 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
9 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 * $Id: nvram_linux.c,v 1.8 2008/07/04 01:15:09 Exp $
14 #include <linux/config.h>
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
18 #include <linux/string.h>
19 #include <linux/interrupt.h>
20 #include <linux/spinlock.h>
21 #include <linux/slab.h>
22 #include <linux/bootmem.h>
23 #include <linux/fs.h>
24 #include <linux/miscdevice.h>
25 #include <linux/mtd/mtd.h>
26 //#include <mtd/mtd-user.h>
27 #include <asm/addrspace.h>
28 #include <asm/io.h>
29 #include <asm/uaccess.h>
30 #include <asm/cacheflush.h>
32 #include <typedefs.h>
33 #include <bcmendian.h>
34 #include <bcmnvram.h>
35 #include <bcmutils.h>
36 #include <bcmdefs.h>
37 #include <hndsoc.h>
38 #include <siutils.h>
39 #include <hndmips.h>
40 #include <sflash.h>
41 #include <linux/delay.h>
42 #ifdef NFLASH_SUPPORT
43 #include <nflash.h>
44 #endif
46 /* In BSS to minimize text size and page aligned so it can be mmap()-ed */
47 static char nvram_buf[NVRAM_SPACE] __attribute__((aligned(PAGE_SIZE)));
48 static char *nvram_commit_buf = NULL;
50 //#define CFE_UPDATE // added by Chen-I for mac/regulation update
51 #ifdef CFE_UPDATE
52 //#include <sbextif.h>
54 extern void bcm947xx_watchdog_disable(void);
56 #define CFE_SPACE 256*1024
57 #define CFE_NVRAM_START 0x00000
58 #define CFE_NVRAM_END 0x01fff
59 #define CFE_NVRAM_SPACE 64*1024
60 static struct mtd_info *cfe_mtd = NULL;
61 static char *CFE_NVRAM_PREFIX="asuscfe";
62 static char *CFE_NVRAM_COMMIT="asuscfecommit";
63 static char *CFE_NVRAM_WATCHDOG="asuscfewatchdog";
64 char *cfe_buf;// = NULL;
65 struct nvram_header *cfe_nvram_header; // = NULL;
67 static u_int32_t cfe_offset;
68 static u_int32_t cfe_embedded_size;
69 static int get_embedded_block(struct mtd_info *mtd, char *buf, size_t erasesize,
70 u_int32_t *offset, struct nvram_header **header, u_int32_t *emb_size);
72 static int cfe_init(void);
73 static int cfe_update(const char *keyword, const char *value);
74 static int cfe_dump(void);
75 static int cfe_commit(void);
76 #endif
79 #define WPS 0
81 #ifdef MODULE
83 #define early_nvram_get(name) nvram_get(name)
85 #else /* !MODULE */
87 /* Global SB handle */
88 extern si_t *bcm947xx_sih;
89 extern spinlock_t bcm947xx_sih_lock;
91 /* Convenience */
92 #define sih bcm947xx_sih
93 #define sih_lock bcm947xx_sih_lock
94 #define KB * 1024
95 #define MB * 1024 * 1024
97 //#define NLS_XFR 1 /* added by Jiahao for WL500gP */
98 #ifdef NLS_XFR
100 #include <linux/nls.h>
102 static char *NLS_NVRAM_U2C="asusnlsu2c";
103 static char *NLS_NVRAM_C2U="asusnlsc2u";
104 __u16 unibuf[1024];
105 char codebuf[1024];
106 char tmpbuf[1024];
108 void
109 asusnls_u2c(char *name)
111 char *codepage;
112 char *xfrstr;
113 struct nls_table *nls;
114 int ret, len;
116 strcpy(codebuf, name);
117 codepage=codebuf+strlen(NLS_NVRAM_U2C);
118 if((xfrstr=strchr(codepage, '_')))
120 *xfrstr=NULL;
121 xfrstr++;
122 /* debug message, start */
124 printk("%s, xfr from utf8 to %s\n", xfrstr, codepage);
125 int j;
126 printk("utf8: %d, ", strlen(xfrstr));
127 for(j=0;j<strlen(xfrstr);j++)
128 printk("%X ", (unsigned char)xfrstr[j]);
129 printk("\n");
131 /* debug message, end */
133 nls=load_nls(codepage);
134 if(!nls)
136 printk("NLS table is null!!\n");
138 else {
139 len = 0;
140 if (ret=utf8_mbstowcs(unibuf, xfrstr, strlen(xfrstr)))
142 int i;
143 for (i = 0; (i < ret) && unibuf[i]; i++) {
144 int charlen;
145 charlen = nls->uni2char(unibuf[i], &name[len], NLS_MAX_CHARSET_SIZE);
146 if (charlen > 0) {
147 len += charlen;
149 else {
150 //name[len++] = '?';
151 strcpy(name, "");
152 unload_nls(nls);
153 return;
156 name[len] = 0;
158 unload_nls(nls);
159 /* debug message, start */
161 int i;
162 printk("unicode: %d, ", ret);
163 for (i=0;i<ret;i++)
164 printk("%X ", unibuf[i]);
165 printk("\n");
166 printk("local: %d, ", strlen(name));
167 for (i=0;i<strlen(name);i++)
168 printk("%X ", (unsigned char)name[i]);
169 printk("\n");
170 printk("local: %s\n", name);
172 /* debug message, end */
174 if(!len)
176 printk("can not xfr from utf8 to %s\n", codepage);
177 strcpy(name, "");
181 else
183 strcpy(name, "");
187 void
188 asusnls_c2u(char *name)
190 char *codepage;
191 char *xfrstr;
192 struct nls_table *nls;
193 int ret;
195 strcpy(codebuf, name);
196 codepage=codebuf+strlen(NLS_NVRAM_C2U);
197 if((xfrstr=strchr(codepage, '_')))
199 *xfrstr=NULL;
200 xfrstr++;
202 /* debug message, start */
204 printk("%s, xfr from %s to utf8\n", xfrstr, codepage);
205 printk("local: %d, ", strlen(xfrstr));
206 int j;
207 for (j=0;j<strlen(xfrstr);j++)
208 printk("%X ", (unsigned char)xfrstr[j]);
209 printk("\n");
210 printk("local: %s\n", xfrstr);
212 /* debug message, end */
214 strcpy(name, "");
215 nls=load_nls(codepage);
216 if(!nls)
218 printk("NLS table is null!!\n");
220 else
222 int charlen;
223 int i;
224 int len = strlen(xfrstr);
225 for (i = 0; len && *xfrstr; i++, xfrstr += charlen, len -= charlen) { /* string to unicode */
226 charlen = nls->char2uni(xfrstr, len, &unibuf[i]);
227 if (charlen < 1) {
228 //unibuf[i] = 0x003f; /* a question mark */
229 //charlen = 1;
230 strcpy(name ,"");
231 unload_nls(nls);
232 return;
235 unibuf[i] = 0;
236 ret=utf8_wcstombs(name, unibuf, 1024); /* unicode to utf-8, 1024 is size of array unibuf */
237 name[ret]=0;
238 unload_nls(nls);
239 /* debug message, start */
241 int k;
242 printk("unicode: %d, ", i);
243 for(k=0;k<i;k++)
244 printk("%X ", unibuf[k]);
245 printk("\n");
246 printk("utf-8: %s, %d, ", name, strlen(name));
247 for (i=0;i<strlen(name);i++)
248 printk("%X ", (unsigned char)name[i]);
249 printk("\n");
251 /* debug message, end */
252 if(!ret)
254 printk("can not xfr from %s to utf8\n", codepage);
255 strcpy(name, "");
259 else
261 strcpy(name, "");
265 /* Jiahao */
266 static int
267 nvram_xfr(char *buf)
269 char *name = tmpbuf;
270 ssize_t ret=0;
272 printk("nvram xfr 1: %s\n", buf);
273 if (copy_from_user(name, buf, strlen(buf)+1)) {
274 ret = -EFAULT;
275 goto done;
278 if (strncmp(tmpbuf, NLS_NVRAM_U2C, strlen(NLS_NVRAM_U2C))==0)
280 asusnls_u2c(tmpbuf);
282 else if (strncmp(buf, NLS_NVRAM_C2U, strlen(NLS_NVRAM_C2U))==0)
284 asusnls_c2u(tmpbuf);
286 else
288 strcpy(tmpbuf, "");
289 printk("nvram xfr 2: %s\n", tmpbuf);
292 if (copy_to_user(buf, tmpbuf, strlen(tmpbuf)+1))
294 ret = -EFAULT;
295 goto done;
297 printk("nvram xfr 3: %s\n", tmpbuf);
299 done:
300 return ret;
303 #endif
305 static int
306 nvram_valid(struct nvram_header *header)
308 return (header->magic == NVRAM_MAGIC) &&
309 (header->len >= sizeof(struct nvram_header)) && (header->len <= NVRAM_SPACE)
310 #if 0
311 && (nvram_calc_crc(header) == (uint8) header->crc_ver_init))
312 #endif
316 /* Probe for NVRAM header */
317 static int
318 early_nvram_init(void)
320 struct nvram_header *header;
321 chipcregs_t *cc;
322 struct sflash *info = NULL;
323 int i;
324 uint32 base, off, lim;
325 u32 *src, *dst;
326 #ifdef NFLASH_SUPPORT
327 uint32 fltype;
328 struct nflash *nfl_info = NULL;
329 uint32 blocksize;
330 #endif
332 if ((cc = si_setcore(sih, CC_CORE_ID, 0)) != NULL) {
333 #ifdef NFLASH_SUPPORT
334 if ((sih->ccrev >= 38) && ((sih->chipst & (1 << 4)) != 0)) {
335 fltype = NFLASH;
336 base = KSEG1ADDR(SI_FLASH1);
337 } else {
338 fltype = readl(&cc->capabilities) & CC_CAP_FLASH_MASK;
339 base = KSEG1ADDR(SI_FLASH2);
341 switch (fltype)
342 #else
343 base = KSEG1ADDR(SI_FLASH2);
344 switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK)
345 #endif
346 switch (readl(&cc->capabilities) & CC_CAP_FLASH_MASK) {
347 case PFLASH:
348 lim = SI_FLASH2_SZ;
349 break;
351 case SFLASH_ST:
352 case SFLASH_AT:
353 if ((info = sflash_init(sih, cc)) == NULL)
354 return -1;
355 lim = info->size;
356 break;
357 #ifdef NFLASH_SUPPORT
358 case NFLASH:
359 if ((nfl_info = nflash_init(sih, cc)) == NULL)
360 return -1;
361 lim = SI_FLASH1_SZ;
362 break;
363 #endif
364 case FLASH_NONE:
365 default:
366 return -1;
368 } else {
369 /* extif assumed, Stop at 4 MB */
370 base = KSEG1ADDR(SI_FLASH1);
371 lim = SI_FLASH1_SZ;
373 #ifdef NFLASH_SUPPORT
374 if (nfl_info != NULL) {
375 blocksize = nfl_info->blocksize;
376 off = blocksize;
377 while (off <= lim) {
378 if (nflash_checkbadb(sih, cc, off) != 0) {
379 off += blocksize;
380 continue;
382 header = (struct nvram_header *) KSEG1ADDR(base + off);
383 if (header->magic == NVRAM_MAGIC)
384 if (nvram_calc_crc(header) == (uint8) header->crc_ver_init) {
385 goto found;
387 off += blocksize;
389 } else {
390 #endif
392 off = FLASH_MIN;
394 #ifdef NVRAM_64K_SUPPORT
395 header = (struct nvram_header *) KSEG1ADDR(base + lim - 0x8000);
396 if(header->magic==0xffffffff) {
397 header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
398 if (nvram_valid(header))
399 goto found;
401 #endif
403 while (off <= lim) {
404 /* Windowed flash access */
405 header = (struct nvram_header *) KSEG1ADDR(base + off - NVRAM_SPACE);
406 if (nvram_valid(header))
407 goto found;
408 off <<= 1;
410 #ifdef NFLASH_SUPPORT
412 #endif
414 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
415 header = (struct nvram_header *) KSEG1ADDR(base + 4 KB);
416 if (nvram_valid(header))
417 goto found;
419 header = (struct nvram_header *) KSEG1ADDR(base + 1 KB);
420 if (nvram_valid(header))
421 goto found;
423 return -1;
425 found:
426 src = (u32 *) header;
427 dst = (u32 *) nvram_buf;
428 for (i = 0; i < sizeof(struct nvram_header); i += 4)
429 *dst++ = *src++;
430 for (; i < header->len && i < NVRAM_SPACE; i += 4)
431 *dst++ = ltoh32(*src++);
433 return 0;
436 /* Early (before mm or mtd) read-only access to NVRAM */
437 static char *
438 early_nvram_get(const char *name)
440 char *var, *value, *end, *eq;
442 if (!name)
443 return NULL;
445 /* Too early? */
446 if (sih == NULL)
447 return NULL;
449 if (!nvram_buf[0])
450 if (early_nvram_init() != 0) {
451 printk("early_nvram_get: Failed reading nvram var %s\n", name);
452 return NULL;
455 /* Look for name=value and return value */
456 var = &nvram_buf[sizeof(struct nvram_header)];
457 end = nvram_buf + sizeof(nvram_buf) - 2;
458 end[0] = end[1] = '\0';
459 for (; *var; var = value + strlen(value) + 1) {
460 if (!(eq = strchr(var, '=')))
461 break;
462 value = eq + 1;
463 if ((eq - var) == strlen(name) && strncmp(var, name, (eq - var)) == 0)
464 return value;
467 return NULL;
470 static int
471 early_nvram_getall(char *buf, int count)
473 char *var, *end;
474 int len = 0;
476 /* Too early? */
477 if (sih == NULL)
478 return -1;
480 if (!nvram_buf[0])
481 if (early_nvram_init() != 0) {
482 printk("early_nvram_getall: Failed reading nvram var\n");
483 return -1;
486 bzero(buf, count);
488 /* Write name=value\0 ... \0\0 */
489 var = &nvram_buf[sizeof(struct nvram_header)];
490 end = nvram_buf + sizeof(nvram_buf) - 2;
491 end[0] = end[1] = '\0';
492 for (; *var; var += strlen(var) + 1) {
493 if ((count - len) <= (strlen(var) + 1))
494 break;
495 len += sprintf(buf + len, "%s", var) + 1;
498 return 0;
500 #endif /* !MODULE */
502 extern char * _nvram_get(const char *name);
503 extern int _nvram_set(const char *name, const char *value);
504 extern int _nvram_unset(const char *name);
505 extern int _nvram_getall(char *buf, int count);
506 extern int _nvram_commit(struct nvram_header *header);
507 extern int _nvram_init(void *sih);
508 extern void _nvram_exit(void);
510 /* Globals */
511 static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED;
512 static struct semaphore nvram_sem;
513 static unsigned long nvram_offset = 0;
514 static int nvram_major = -1;
515 static struct class *nvram_class = NULL;
516 static struct mtd_info *nvram_mtd = NULL;
519 _nvram_read(char *buf)
521 struct nvram_header *header = (struct nvram_header *) buf;
522 size_t len;
524 #ifdef NFLASH_SUPPORT
525 int offset = 0;
526 if (nvram_mtd) {
527 if (nvram_mtd->type == MTD_NANDFLASH)
528 offset = 0;
529 else
530 offset = nvram_mtd->size - NVRAM_SPACE;
532 if (!nvram_mtd ||
533 nvram_mtd->read(nvram_mtd, offset, NVRAM_SPACE, &len, buf) ||
534 len != NVRAM_SPACE ||
535 !nvram_valid(header)) {
536 /* Maybe we can recover some data from early initialization */
537 memcpy(buf, nvram_buf, NVRAM_SPACE);
539 #else
540 if (!nvram_mtd ||
541 nvram_mtd->read(nvram_mtd, nvram_mtd->size - NVRAM_SPACE, NVRAM_SPACE, &len, buf) ||
542 len != NVRAM_SPACE ||
543 !nvram_valid(header)) {
544 /* Maybe we can recover some data from early initialization */
545 memcpy(buf, nvram_buf, NVRAM_SPACE);
547 #endif
549 return 0;
552 struct nvram_tuple *
553 _nvram_realloc(struct nvram_tuple *t, const char *name, const char *value)
555 if ((nvram_offset + strlen(value) + 1) > NVRAM_SPACE)
556 return NULL;
558 if (!t) {
559 if (!(t = kmalloc(sizeof(struct nvram_tuple) + strlen(name) + 1, GFP_ATOMIC)))
560 return NULL;
562 /* Copy name */
563 t->name = (char *) &t[1];
564 strcpy(t->name, name);
566 t->value = NULL;
569 /* Copy value */
570 if (!t->value || strcmp(t->value, value)) {
571 t->value = &nvram_buf[nvram_offset];
572 strcpy(t->value, value);
573 nvram_offset += strlen(value) + 1;
576 return t;
579 void
580 _nvram_free(struct nvram_tuple *t)
582 if (!t)
583 nvram_offset = 0;
584 else
585 kfree(t);
589 nvram_init(void *sih)
591 return 0;
595 nvram_set(const char *name, const char *value)
597 unsigned long flags;
598 int ret;
599 struct nvram_header *header;
600 #if WPS
601 char wps_name[32];
602 int wep_len;
603 #endif
605 spin_lock_irqsave(&nvram_lock, flags);
607 //printk("nvram_set: name = %s, value = %s!\n", name, value);
608 #ifdef CFE_UPDATE //write back to default sector as well, Chen-I
609 if(strncmp(name, CFE_NVRAM_PREFIX, strlen(CFE_NVRAM_PREFIX))==0)
611 if(strcmp(name, CFE_NVRAM_COMMIT)==0)
612 cfe_commit();
613 else if(strcmp(name, "asuscfe_dump") == 0)
614 ret = cfe_dump();
615 else if(strcmp(name, CFE_NVRAM_WATCHDOG)==0)
617 bcm947xx_watchdog_disable();
619 else
621 cfe_update(name+strlen(CFE_NVRAM_PREFIX), value);
622 _nvram_set(name+strlen(CFE_NVRAM_PREFIX), value);
625 else
626 #endif
628 #if WPS
629 if (strncmp(name, "wlx_", 4) == 0) {
630 memset(wps_name, 0, sizeof(wps_name));
631 sprintf(wps_name, "wl0_%s", name+4);
632 ret = _nvram_set(wps_name, value);
633 spin_unlock_irqrestore(&nvram_lock, flags);
634 return ret;
637 if (strncmp(name, "wl0_", 4) == 0)
639 /* Authentication mode */
640 if (strncmp(name, "wl0_akm", 7) == 0) {
641 if (strncmp(value, "psk2", 4) == 0) { // WPA2-Personal
642 _nvram_set("wl_auth_mode", "psk");
643 _nvram_set("wl_wpa_mode", "2");
645 else if (strncmp(value, "psk ", 4) == 0) { // WPA-Auto-Personal
646 _nvram_set("wl_auth_mode", "psk");
647 _nvram_set("wl_wpa_mode", "0");
649 else if (strncmp(value, "psk", 3) == 0) { // WPA-Personal
650 _nvram_set("wl_auth_mode", "psk");
651 _nvram_set("wl_wpa_mode", "1");
653 else if (strncmp(value, "wpa2", 4) == 0) { // WPA2-Enterprise
654 _nvram_set("wl_auth_mode", "wpa2");
656 else if (strncmp(value, "wpa ", 4) == 0) { // WPA-Auto-Enterprise
657 _nvram_set("wl_wpa_mode", "4");
658 _nvram_set("wl_auth_mode", "wpa");
660 else if (strncmp(value, "wpa", 3) == 0) { // WPA-Enterprise
661 _nvram_set("wl_wpa_mode", "3");
662 _nvram_set("wl_auth_mode", "wpa");
664 _nvram_set("wl_akm", value);
666 /* WPS KEY*/
667 else if (strcmp(name, "wl0_wpa_psk") == 0) {
668 _nvram_set("wl_wpa_psk", value);
670 /* WEP type */
671 #if 1
672 else if ((strncmp(name, "wl0_key", 7) == 0 )) {
674 wep_len = strlen (value);
675 memset(wps_name, 0, sizeof(wps_name));
677 if ((wep_len == 5) || (wep_len == 10)) { /* wl0_key1~4*/
678 // _nvram_set ("wl0_wep_x", "1");
679 _nvram_set ("wl_wep_x", "1");
680 sprintf(wps_name, "wl_%s", name+4);
682 else if ((wep_len == 13) || (wep_len == 26)) {
683 // _nvram_set ("wl0_wep_x", "2");
684 _nvram_set ("wl_wep_x", "2");
685 sprintf(wps_name, "wl_%s", name+4);
687 else { /* wl0_key index */
688 sprintf(wps_name, "wl_%s", name+4);
690 _nvram_set(wps_name, value);
692 #endif
693 else if (strcmp(name, "wl0_ssid") == 0) {
694 // _nvram_set("wl0_ssid2", value);
695 // _nvram_set("wl_ssid2", value);
696 _nvram_set("wl_ssid", value);
698 else if (strcmp(name, "wl0_crypto") == 0) {
699 _nvram_set("wl_crypto", value);
701 else if (strncmp(name, "wl0_wps", 7) == 0) {
702 memset(wps_name, 0, sizeof(wps_name));
703 sprintf(wps_name, "wl_%s", name+4);
704 _nvram_set(wps_name, value);
708 else if (strncmp(name, "wps_random_ssid_prefix", 22) == 0) {
709 memset(wps_name, 0, sizeof(wps_name));
710 sprintf(wps_name, "ASUS_");
711 ret = _nvram_set("wps_random_ssid_prefix", wps_name);
712 spin_unlock_irqrestore(&nvram_lock, flags);
713 return ret;
716 if (strcmp(name, "lan_wps_oob") == 0) {
717 if (strcmp(value, "disabled") == 0) {
718 _nvram_set("wps_config_state", "1");
719 _nvram_set("wl_wps_config_state", "1");
720 _nvram_set("wl0_wps_config_state", "1");
721 } else if (strcmp(value, "enabled") == 0) {
722 _nvram_set("wps_config_state", "0");
723 _nvram_set("wl_wps_config_state", "0");
724 _nvram_set("wl0_wps_config_state", "0");
728 if (strcmp(name, "wps_config_state") == 0) {
729 if (strcmp(value, "0") == 0)
730 _nvram_set("lan_wps_oob", "enabled");
731 else if (strcmp(value, "1") == 0)
732 _nvram_set("lan_wps_oob", "disabled");
735 if ((strcmp(name, "wl_wps_config_state") == 0) || (strcmp(name, "wl0_wps_config_state") == 0))
736 _nvram_set("wps_config_state", value);
739 // else if ((strncmp(name, "wps_proc_status", 15) == 0 ) && (strcmp(value, "4"))) /* WPS success*/
740 // _nvram_set("wps_config_state", "1");
742 #if 0
743 if(!strcmp(name, "wl0_ssid"))
744 _nvram_set("wl_ssid", value);
745 if(!strcmp(name, "wl0_ssid"))
746 _nvram_set("wl_ssid", value);
747 /* Set Wireless encryption */
748 if (!strcmp(name, "wl0_akm")) {
749 _nvram_set("wl_auth_mode", "psk");
750 _nvram_set("wl_wpa_mode", "1");
752 else if (!strcmp("wl0_akm", "psk2")) {
753 _nvram_set("wl_auth_mode", "psk");
754 _nvram_set("wl_wpa_mode", "2");
756 else if (nvram_match("wl0_akm", "wpa")) {
757 _nvram_set("wl_auth_mode", "wpa");
758 _nvram_set("wl_wpa_mode", "3");
760 else if (nvram_match("wl0_akm", "wpa2")) {
761 _nvram_set("wl_auth_mode", "wpa2");
763 else
764 _nvram_set("wl_auth_mode", nvram_get("wl0_auth_mode"));
765 #endif
766 #endif
768 if ((ret = _nvram_set(name, value))) {
769 /* Consolidate space and try again */
770 if ((header = kmalloc(NVRAM_SPACE, GFP_ATOMIC))) {
771 if (_nvram_commit(header) == 0)
772 ret = _nvram_set(name, value);
773 kfree(header);
776 spin_unlock_irqrestore(&nvram_lock, flags);
778 return ret;
781 char *
782 real_nvram_get(const char *name)
784 unsigned long flags;
785 char *value;
787 spin_lock_irqsave(&nvram_lock, flags);
788 value = _nvram_get(name);
789 spin_unlock_irqrestore(&nvram_lock, flags);
791 return value;
794 char *
795 nvram_get(const char *name)
797 if (nvram_major >= 0)
798 return real_nvram_get(name);
799 else
800 return early_nvram_get(name);
804 nvram_unset(const char *name)
806 unsigned long flags;
807 int ret;
809 spin_lock_irqsave(&nvram_lock, flags);
810 #ifdef CFE_UPDATE //unset variable in embedded nvram
811 if(strncmp(name, CFE_NVRAM_PREFIX, strlen(CFE_NVRAM_PREFIX))==0)
813 if((ret = cfe_update(name+strlen(CFE_NVRAM_PREFIX), NULL)) == 0)
815 ret = _nvram_unset(name+strlen(CFE_NVRAM_PREFIX));
818 else
819 #endif
820 ret = _nvram_unset(name);
821 spin_unlock_irqrestore(&nvram_lock, flags);
823 return ret;
826 static void
827 erase_callback(struct erase_info *done)
829 wait_queue_head_t *wait_q = (wait_queue_head_t *) done->priv;
830 wake_up(wait_q);
833 #ifdef NFLASH_SUPPORT
835 nvram_nflash_commit(void)
837 char *buf;
838 size_t len, magic_len;
839 unsigned int i;
840 int ret;
841 struct nvram_header *header;
842 unsigned long flags;
843 u_int32_t offset;
844 struct erase_info erase;
846 if (!(buf = kmalloc(NVRAM_SPACE, GFP_KERNEL))) {
847 printk("nvram_commit: out of memory\n");
848 return -ENOMEM;
851 down(&nvram_sem);
853 /* read header for checking */
854 offset = 0;
855 i = sizeof(struct nvram_header);
856 ret = nvram_mtd->read(nvram_mtd, offset, i, &len, buf);
857 if (ret || len != i) {
858 printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i);
859 ret = -EIO;
860 goto done;
863 header = (struct nvram_header *)buf;
864 /* do NOT commit after loaddefault */
865 if (header->magic == NVRAM_INVALID_MAGIC) {
866 printk(KERN_EMERG "nvram_commit: NOT allow commit, magic = 0x%x\n",
867 header->magic);
868 ret = -EPERM;
869 goto done;
872 offset = 0;
873 header = (struct nvram_header *)buf;
874 header->magic = NVRAM_MAGIC;
875 /* reset MAGIC before we regenerate the NVRAM,
876 * otherwise we'll have an incorrect CRC
878 /* Regenerate NVRAM */
879 spin_lock_irqsave(&nvram_lock, flags);
880 ret = _nvram_commit(header);
881 spin_unlock_irqrestore(&nvram_lock, flags);
882 if (ret)
883 goto done;
885 /* Write partition up to end of data area */
886 i = header->len;
887 ret = nvram_mtd->write(nvram_mtd, offset, i, &len, buf);
888 if (ret || len != i) {
889 printk("nvram_commit: write error\n");
890 ret = -EIO;
891 goto done;
894 done:
895 up(&nvram_sem);
896 kfree(buf);
897 return ret;
899 #endif
902 nvram_commit(void)
904 #if 0
905 char *buf;
906 #endif
907 size_t erasesize, len, magic_len;
908 unsigned int i;
909 int ret;
910 struct nvram_header *header;
911 unsigned long flags;
912 u_int32_t offset;
913 DECLARE_WAITQUEUE(wait, current);
914 wait_queue_head_t wait_q;
915 struct erase_info erase;
916 u_int32_t magic_offset = 0; /* Offset for writing MAGIC # */
918 if (!nvram_mtd) {
919 printk("nvram_commit: NVRAM not found\n");
920 return -ENODEV;
923 if (in_interrupt()) {
924 printk("nvram_commit: not committing in interrupt\n");
925 return -EINVAL;
928 #ifdef NFLASH_SUPPORT
929 if (nvram_mtd->type == MTD_NANDFLASH)
930 return nvram_nflash_commit();
931 #endif
932 /* Backup sector blocks to be erased */
933 erasesize = ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize);
934 #if 0
935 if (!(buf = kmalloc(erasesize, GFP_KERNEL))) {
936 printk("nvram_commit: out of memory\n");
937 return -ENOMEM;
939 #endif
940 down(&nvram_sem);
942 if ((i = erasesize - NVRAM_SPACE) > 0) {
943 offset = nvram_mtd->size - erasesize;
944 len = 0;
945 ret = nvram_mtd->read(nvram_mtd, offset, i, &len, nvram_commit_buf);
946 if (ret || len != i) {
947 printk("nvram_commit: read error ret = %d, len = %d/%d\n", ret, len, i);
948 ret = -EIO;
949 goto done;
951 header = (struct nvram_header *)(nvram_commit_buf + i);
952 magic_offset = i + ((void *)&header->magic - (void *)header);
953 } else {
954 offset = nvram_mtd->size - NVRAM_SPACE;
955 magic_offset = ((void *)&header->magic - (void *)header);
956 header = (struct nvram_header *)nvram_commit_buf;
959 /* clear the existing magic # to mark the NVRAM as unusable
960 * we can pull MAGIC bits low without erase
962 header->magic = NVRAM_CLEAR_MAGIC; /* All zeros magic */
963 /* Unlock sector blocks */
964 if (nvram_mtd->unlock)
965 nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize);
966 ret = nvram_mtd->write(nvram_mtd, offset + magic_offset, sizeof(header->magic),
967 &magic_len, (char *)&header->magic);
968 if (ret || magic_len != sizeof(header->magic)) {
969 printk("nvram_commit: clear MAGIC error\n");
970 ret = -EIO;
971 goto done;
974 header->magic = NVRAM_MAGIC;
975 /* reset MAGIC before we regenerate the NVRAM,
976 * otherwise we'll have an incorrect CRC
978 /* Regenerate NVRAM */
979 spin_lock_irqsave(&nvram_lock, flags);
980 ret = _nvram_commit(header);
981 spin_unlock_irqrestore(&nvram_lock, flags);
982 if (ret)
983 goto done;
985 /* Erase sector blocks */
986 init_waitqueue_head(&wait_q);
987 for (; offset < nvram_mtd->size - NVRAM_SPACE + header->len;
988 offset += nvram_mtd->erasesize) {
990 erase.mtd = nvram_mtd;
991 erase.addr = offset;
992 erase.len = nvram_mtd->erasesize;
993 erase.callback = erase_callback;
994 erase.priv = (u_long) &wait_q;
996 set_current_state(TASK_INTERRUPTIBLE);
997 add_wait_queue(&wait_q, &wait);
999 /* Unlock sector blocks */
1000 if (nvram_mtd->unlock)
1001 nvram_mtd->unlock(nvram_mtd, offset, nvram_mtd->erasesize);
1003 if ((ret = nvram_mtd->erase(nvram_mtd, &erase))) {
1004 set_current_state(TASK_RUNNING);
1005 remove_wait_queue(&wait_q, &wait);
1006 printk("nvram_commit: erase error\n");
1007 goto done;
1010 /* Wait for erase to finish */
1011 schedule();
1012 remove_wait_queue(&wait_q, &wait);
1015 /* Write partition up to end of data area */
1016 header->magic = NVRAM_INVALID_MAGIC; /* All ones magic */
1017 offset = nvram_mtd->size - erasesize;
1018 i = erasesize - NVRAM_SPACE + header->len;
1019 ret = nvram_mtd->write(nvram_mtd, offset, i, &len, nvram_commit_buf);
1020 if (ret || len != i) {
1021 printk("nvram_commit: write error\n");
1022 ret = -EIO;
1023 goto done;
1026 /* Now mark the NVRAM in flash as "valid" by setting the correct
1027 * MAGIC #
1029 header->magic = NVRAM_MAGIC;
1030 ret = nvram_mtd->write(nvram_mtd, offset + magic_offset, sizeof(header->magic),
1031 &magic_len, (char *)&header->magic);
1032 if (ret || magic_len != sizeof(header->magic)) {
1033 printk("nvram_commit: write MAGIC error\n");
1034 ret = -EIO;
1035 goto done;
1038 offset = nvram_mtd->size - erasesize;
1039 ret = nvram_mtd->read(nvram_mtd, offset, 4, &len, nvram_commit_buf);
1041 #ifdef NVRAM_64K_SUPPORT /*Only for RT-N66U upgrade from nvram 32K -> 64K*/
1042 if(header->len < 0x8001){
1043 char *log_buf;
1044 u_int32_t offset_t;
1045 size_t log_len;
1047 offset_t = 0x18000;
1048 log_buf =0x01020304;
1049 ret = nvram_mtd->write(nvram_mtd, offset_t, sizeof(log_buf), &log_len, &log_buf);
1051 #endif
1053 done:
1054 up(&nvram_sem);
1055 #if 0
1056 kfree(buf);
1057 #endif
1058 return ret;
1062 nvram_getall(char *buf, int count)
1064 unsigned long flags;
1065 int ret;
1067 spin_lock_irqsave(&nvram_lock, flags);
1068 if (nvram_major >= 0)
1069 ret = _nvram_getall(buf, count);
1070 else
1071 ret = early_nvram_getall(buf, count);
1072 spin_unlock_irqrestore(&nvram_lock, flags);
1074 return ret;
1077 EXPORT_SYMBOL(nvram_init);
1078 EXPORT_SYMBOL(nvram_get);
1079 EXPORT_SYMBOL(nvram_getall);
1080 EXPORT_SYMBOL(nvram_set);
1081 EXPORT_SYMBOL(nvram_unset);
1082 EXPORT_SYMBOL(nvram_commit);
1084 /* User mode interface below */
1086 static ssize_t
1087 dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos)
1089 char tmp[100], *name = tmp, *value;
1090 ssize_t ret;
1091 unsigned long off;
1093 if (count > sizeof(tmp)) {
1094 if (!(name = kmalloc(count, GFP_KERNEL)))
1095 return -ENOMEM;
1098 if (copy_from_user(name, buf, count)) {
1099 ret = -EFAULT;
1100 goto done;
1103 if (*name == '\0') {
1104 /* Get all variables */
1105 ret = nvram_getall(name, count);
1106 if (ret == 0) {
1107 if (copy_to_user(buf, name, count)) {
1108 ret = -EFAULT;
1109 goto done;
1111 ret = count;
1113 } else {
1114 if (!(value = nvram_get(name))) {
1115 ret = 0;
1116 goto done;
1119 /* Provide the offset into mmap() space */
1120 off = (unsigned long) value - (unsigned long) nvram_buf;
1122 if (put_user(off, (unsigned long *) buf)) {
1123 ret = -EFAULT;
1124 goto done;
1127 ret = sizeof(unsigned long);
1130 flush_cache_all();
1132 done:
1133 if (name != tmp)
1134 kfree(name);
1136 return ret;
1139 static ssize_t
1140 dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
1142 char tmp[100], *name = tmp, *value;
1143 ssize_t ret;
1145 if (count > sizeof(tmp)) {
1146 if (!(name = kmalloc(count, GFP_KERNEL)))
1147 return -ENOMEM;
1150 if (copy_from_user(name, buf, count)) {
1151 ret = -EFAULT;
1152 goto done;
1155 value = name;
1156 name = strsep(&value, "=");
1157 if (value)
1158 ret = nvram_set(name, value) ? : count;
1159 else
1160 ret = nvram_unset(name) ? : count;
1162 done:
1163 if (name != tmp)
1164 kfree(name);
1166 return ret;
1169 static int
1170 dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
1172 if (cmd != NVRAM_MAGIC)
1173 return -EINVAL;
1175 #ifndef NLS_XFR
1176 return nvram_commit();
1177 #else
1178 if(arg == 0)
1179 return nvram_commit();
1180 else
1181 return nvram_xfr((char *)arg);
1182 #endif // NLS_XFR
1185 static int
1186 dev_nvram_mmap(struct file *file, struct vm_area_struct *vma)
1188 unsigned long offset = __pa(nvram_buf) >> PAGE_SHIFT;
1190 if (remap_pfn_range(vma, vma->vm_start, offset,
1191 vma->vm_end - vma->vm_start,
1192 vma->vm_page_prot))
1193 return -EAGAIN;
1195 return 0;
1198 static int
1199 dev_nvram_open(struct inode *inode, struct file * file)
1201 return 0;
1204 static int
1205 dev_nvram_release(struct inode *inode, struct file * file)
1207 return 0;
1210 static struct file_operations dev_nvram_fops = {
1211 owner: THIS_MODULE,
1212 open: dev_nvram_open,
1213 release: dev_nvram_release,
1214 read: dev_nvram_read,
1215 write: dev_nvram_write,
1216 ioctl: dev_nvram_ioctl,
1217 mmap: dev_nvram_mmap
1220 static void
1221 dev_nvram_exit(void)
1223 int order = 0;
1224 struct page *page, *end;
1226 if (nvram_class) {
1227 class_device_destroy(nvram_class, MKDEV(nvram_major, 0));
1228 class_destroy(nvram_class);
1231 if (nvram_major >= 0)
1232 unregister_chrdev(nvram_major, "nvram");
1234 if (nvram_mtd)
1235 put_mtd_device(nvram_mtd);
1237 while ((PAGE_SIZE << order) < NVRAM_SPACE)
1238 order++;
1239 end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
1240 for (page = virt_to_page(nvram_buf); page <= end; page++)
1241 ClearPageReserved(page);
1243 _nvram_exit();
1246 static int
1247 dev_nvram_init(void)
1249 int order = 0, ret = 0;
1250 struct page *page, *end;
1251 unsigned int i;
1252 osl_t *osh;
1254 /* Allocate and reserve memory to mmap() */
1255 while ((PAGE_SIZE << order) < NVRAM_SPACE)
1256 order++;
1257 end = virt_to_page(nvram_buf + (PAGE_SIZE << order) - 1);
1258 for (page = virt_to_page(nvram_buf); page <= end; page++) {
1259 SetPageReserved(page);
1262 #if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
1263 /* Find associated MTD device */
1264 for (i = 0; i < MAX_MTD_DEVICES; i++) {
1265 nvram_mtd = get_mtd_device(NULL, i);
1266 if (!IS_ERR(nvram_mtd)) {
1267 if (!strcmp(nvram_mtd->name, "nvram") &&
1268 nvram_mtd->size >= NVRAM_SPACE) {
1269 break;
1271 put_mtd_device(nvram_mtd);
1274 if (i >= MAX_MTD_DEVICES)
1275 nvram_mtd = NULL;
1276 #endif
1278 #ifdef NVRAM_64K_SUPPORT
1279 int ret32;
1280 char *log_buf;
1281 u_int32_t offset_t;
1282 size_t log_len;
1283 DECLARE_WAITQUEUE(wait, current);
1284 wait_queue_head_t wait_q;
1285 struct erase_info erase;
1287 offset_t = 0x18000;
1288 ret32 = nvram_mtd->read(nvram_mtd, offset_t, 4, &log_len, &log_buf);
1289 if(log_buf==0xffffffff) {
1290 /* Erase sector blocks */
1291 init_waitqueue_head(&wait_q);
1293 erase.mtd = nvram_mtd;
1294 erase.addr = 0;
1295 erase.len = nvram_mtd->erasesize;
1296 erase.callback = erase_callback;
1297 erase.priv = (u_long) &wait_q;
1298 set_current_state(TASK_INTERRUPTIBLE);
1299 add_wait_queue(&wait_q, &wait);
1301 /* Unlock sector blocks */
1302 if (nvram_mtd->unlock)
1303 nvram_mtd->unlock(nvram_mtd, 0, nvram_mtd->erasesize);
1305 if ((ret = nvram_mtd->erase(nvram_mtd, &erase))) {
1306 set_current_state(TASK_RUNNING);
1307 remove_wait_queue(&wait_q, &wait);
1308 printk("nvram mtd erase error\n");
1311 /* Wait for erase to finish */
1312 schedule();
1313 remove_wait_queue(&wait_q, &wait);
1315 #endif
1317 /* Initialize hash table lock */
1318 spin_lock_init(&nvram_lock);
1320 /* Initialize commit semaphore */
1321 init_MUTEX(&nvram_sem);
1323 /* Register char device */
1324 if ((nvram_major = register_chrdev(0, "nvram", &dev_nvram_fops)) < 0) {
1325 ret = nvram_major;
1326 goto err;
1329 if (si_osh(sih) == NULL) {
1330 osh = osl_attach(NULL, SI_BUS, FALSE);
1331 if (osh == NULL) {
1332 printk("Error allocating osh\n");
1333 unregister_chrdev(nvram_major, "nvram");
1334 goto err;
1336 si_setosh(sih, osh);
1339 /* Initialize hash table */
1340 _nvram_init(sih);
1342 /* Create /dev/nvram handle */
1343 nvram_class = class_create(THIS_MODULE, "nvram");
1344 if (IS_ERR(nvram_class)) {
1345 printk("Error creating nvram class\n");
1346 goto err;
1349 /* Add the device nvram0 */
1350 class_device_create(nvram_class, NULL, MKDEV(nvram_major, 0), NULL, "nvram");
1352 /* reserve commit read buffer */
1353 /* Backup sector blocks to be erased */
1354 if (!(nvram_commit_buf = kmalloc(ROUNDUP(NVRAM_SPACE, nvram_mtd->erasesize), GFP_KERNEL))) {
1355 printk("dev_nvram_init: nvram_commit_buf out of memory\n");
1356 goto err;
1359 /* Set the SDRAM NCDL value into NVRAM if not already done */
1360 if (getintvar(NULL, "sdram_ncdl") == 0) {
1361 unsigned int ncdl;
1362 char buf[] = "0x00000000";
1364 if ((ncdl = si_memc_get_ncdl(sih))) {
1365 sprintf(buf, "0x%08x", ncdl);
1366 nvram_set("sdram_ncdl", buf);
1367 nvram_commit();
1371 return 0;
1373 err:
1374 dev_nvram_exit();
1375 return ret;
1378 #ifdef CFE_UPDATE
1379 int get_embedded_block(struct mtd_info *mtd, char *buf, size_t erasesize,
1380 u_int32_t *offset, struct nvram_header **header, u_int32_t *emb_size)
1382 size_t len;
1383 struct nvram_header *nvh;
1385 #ifdef CONFIG_RTAN23 /*for AMCC RTAN23 */
1386 *offset = mtd->size - erasesize; /*/at the end of mtd */
1387 *emb_size = 8*1024 - 16; /*/8K - 16 byte */
1388 printk("get_embedded_block: mtd->size(%08x) erasesize(%08x) offset(%08x) emb_size(%08x)\n", mtd->size, erasesize, *offset, *emb_size);
1389 cfe_mtd->read(mtd, *offset, erasesize, &len, buf);
1390 if(len != erasesize)
1391 return -EIO;
1393 /* find nvram header */
1394 nvh = (struct nvram_header *)(buf + erasesize - 8*1024);
1395 if (nvh->magic == NVRAM_MAGIC)
1397 *header = nvh;
1398 return 0;
1401 #else /* for Broadcom WL500 serials */
1402 *offset = 0; /* from the mtd start */
1403 *emb_size = 4096; /* 1K byte */
1404 printk("get_embedded_block: mtd->size(%08x) erasesize(%08x) offset(%08x) emb_size(%08x)\n", mtd->size, erasesize, *offset, *emb_size);
1405 cfe_mtd->read(mtd, *offset, erasesize, &len, buf);
1406 if(len != erasesize)
1407 return -EIO;
1409 /* find nvram header */
1410 nvh = (struct nvram_header *)(buf + (4 * 1024));
1411 if (nvh->magic == NVRAM_MAGIC)
1413 *header = nvh;
1414 return 0;
1416 nvh = (struct nvram_header *)(buf + (1 * 1024));
1417 if (nvh->magic == NVRAM_MAGIC)
1419 *header = nvh;
1420 return 0;
1422 #endif
1423 printk("get_embedded_block: no nvram magic found\n");
1424 return -ENXIO;
1426 static int cfe_init(void)
1428 size_t erasesize;
1429 int i;
1430 int ret = 0;
1432 /* Find associated MTD device */
1433 for (i = 0; i < MAX_MTD_DEVICES; i++) {
1434 cfe_mtd = get_mtd_device(NULL, i);
1435 if (cfe_mtd != NULL) {
1436 printk("cfe_init: CFE MTD %x %s %x\n", i, cfe_mtd->name, cfe_mtd->size);
1437 if (!strcmp(cfe_mtd->name, "boot"))
1438 break;
1439 put_mtd_device(cfe_mtd);
1442 if (i >= MAX_MTD_DEVICES)
1444 printk("cfe_init: No CFE MTD\n");
1445 cfe_mtd = NULL;
1446 ret = -ENODEV;
1449 if(cfe_mtd == NULL) goto fail;
1451 /* sector blocks to be erased and backup */
1452 erasesize = ROUNDUP(CFE_NVRAM_SPACE, cfe_mtd->erasesize);
1454 //printk("cfe_init: block size %d\n", erasesize);
1455 cfe_buf = kmalloc(erasesize, GFP_KERNEL);
1457 if(cfe_buf == NULL)
1459 //printk("cfe_init: No CFE Memory\n");
1460 ret = -ENOMEM;
1461 goto fail;
1463 if((ret = get_embedded_block(cfe_mtd, cfe_buf, erasesize, &cfe_offset, &cfe_nvram_header, &cfe_embedded_size)))
1464 goto fail;
1466 printk("cfe_init: cfe_nvram_header(%08x)\n", (unsigned int) cfe_nvram_header);
1467 bcm947xx_watchdog_disable();
1469 return 0;
1471 fail:
1472 if (cfe_mtd != NULL)
1474 put_mtd_device(cfe_mtd);
1475 cfe_mtd=NULL;
1477 if(cfe_buf != NULL)
1479 kfree(cfe_buf);
1480 cfe_buf=NULL;
1482 return ret;
1484 static int cfe_update(const char *keyword, const char *value)
1486 struct nvram_header *header;
1487 uint8 crc;
1488 int ret;
1489 int found = 0;
1490 char *str, *end, *mv_target = NULL, *mv_start = NULL;
1492 if(keyword == NULL || *keyword == 0)
1493 return 0;
1495 if(cfe_buf == NULL||cfe_mtd == NULL)
1496 if((ret = cfe_init()))
1497 return ret;
1499 header = cfe_nvram_header;
1501 //printk("cfe_update: before %x %x\n", header->len, cfe_nvram_header->crc_ver_init&0xff);
1502 str = (char *) &header[1];
1503 end = (char *) header + cfe_embedded_size - 2;
1504 end[0] = end[1] = '\0';
1505 for (; *str; str += strlen(str) + 1)
1507 if(!found)
1509 if(strncmp(str, keyword, strlen(keyword)) == 0 && str[strlen(keyword)] == '=')
1511 printk("cfe_update: !!!! found !!!!\n");
1512 found = 1;
1513 if(value != NULL && strlen(str) == strlen(keyword) + 1 + strlen(value))
1514 {//string length is the same
1515 strcpy(str+strlen(keyword)+1, value);
1517 else
1519 mv_target = str;
1520 mv_start = str + strlen(str) + 1;
1525 /* str point to the end of all embedded nvram settings */
1527 if(mv_target != NULL)
1528 { /* need to move string */
1529 int str_len = strlen(mv_target);
1530 printk("cfe_update: mv_target(%08x) mv_start(%08x) str(%08x) str_len(%d)\n", (unsigned int)mv_target, (unsigned int)mv_start, (unsigned int)str, str_len);
1531 if(value != NULL && (str + strlen(keyword) + 1 + strlen(value) + 1 - (str_len + 1)) > end)
1532 return -ENOSPC;
1533 memmove(mv_target, mv_start, str - mv_start);
1534 printk("cfe_update: memmove done\n");
1535 str -= (str_len + 1); /* /set str to the end for placing incoming keyword and value there */
1538 if(value == NULL)
1540 printk("cfe_update: do unset\n");
1542 else if(!found || mv_target != NULL) /*new or movement */
1543 { /* append the keyword and value here */
1544 printk("cfe_update: str(%08x)\n", (unsigned int) str);
1545 if((str + strlen(keyword) + 1 + strlen(value) + 1) > end)
1546 return -ENOSPC;
1547 str += sprintf(str, "%s=%s", keyword, value) + 1;
1548 printk("cfe_update: append string\n");
1550 /* calc length */
1551 memset(str, 0, cfe_embedded_size+(char *)header - str);
1552 str += 2;
1553 header->len = ROUNDUP(str - (char *) header, 4);
1554 printk("cfe_update: header len: %x\n", header->len);
1555 /*/calc crc */
1556 crc = nvram_calc_crc(header);
1557 printk("cfe_update: nvram_calc_crc(header) = 0x%02x\n", crc);
1558 header->crc_ver_init = (header->crc_ver_init & NVRAM_CRC_VER_MASK)|crc;
1559 /*/printk("cfe_update: after %x %x\n", header->crc_ver_init&0xFF, crc); */
1560 return 0;
1562 static int cfe_dump(void)
1564 unsigned int i;
1565 int ret;
1566 unsigned char *ptr;
1568 if(cfe_buf == NULL||cfe_mtd == NULL)
1569 if((ret = cfe_init()))
1570 return ret;
1572 printk("cfe_dump: cfe_buf(%08x), dump 1024 byte\n", (unsigned int)cfe_buf);
1573 for(i=0, ptr=(unsigned char *)cfe_nvram_header - 1024; ptr < (unsigned char *)cfe_nvram_header; i++, ptr++)
1575 if(i%16==0) printk("%04x: %02x ", i, *ptr);
1576 else if(i%16==15) printk("%02x\n", *ptr);
1577 else if(i%16==7) printk("%02x - ", *ptr);
1578 else printk("%02x ", *ptr);
1581 printk("\ncfe_dump: cfe_nvram_header(%08x)\n", (unsigned int)cfe_nvram_header);
1582 printk("cfe_dump: cfe_nvram_header->len(0x%08x)\n", cfe_nvram_header->len);
1584 printk("\n####################\n");
1585 for(i=0, ptr=(unsigned char *)cfe_nvram_header; i< cfe_embedded_size; i++, ptr++)
1587 if(i%16==0) printk("%04x: %02x ", i, *ptr);
1588 else if(i%16==15) printk("%02x\n", *ptr);
1589 else if(i%16==7) printk("%02x - ", *ptr);
1590 else printk("%02x ", *ptr);
1592 printk("\n####################\n");
1593 ptr = (unsigned char *)&cfe_nvram_header[1];
1594 while(*ptr)
1596 printk("%s\n", ptr);
1597 ptr += strlen(ptr) + 1;
1599 printk("\n####################\n");
1600 for(i=0, ptr=((unsigned char *)cfe_nvram_header) + cfe_embedded_size; i<16; i++, ptr++)
1602 if(i%16==0) printk("%04x: %02x ", i, *ptr);
1603 else if(i%16==15) printk("%02x\n", *ptr);
1604 else if(i%16==7) printk("%02x - ", *ptr);
1605 else printk("%02x ", *ptr);
1607 return 0;
1610 static int cfe_commit(void)
1612 DECLARE_WAITQUEUE(wait, current);
1613 wait_queue_head_t wait_q;
1614 struct erase_info erase;
1615 int ret = 0;
1616 size_t erasesize, len=0;
1617 u_int32_t offset;
1619 if(cfe_mtd == NULL||cfe_buf == NULL)
1621 printk("cfe_commit: do nothing\n");
1622 return 0;
1625 #if 0
1626 ret = cfe_dump();
1627 return ret;
1628 #endif
1629 #if 1
1630 /* Backup sector blocks to be erased */
1631 erasesize = ROUNDUP(CFE_NVRAM_SPACE, cfe_mtd->erasesize);
1632 printk("cfe_commit: erasesize(%08x) cfe_offset(%08x)\n", erasesize, cfe_offset);
1634 /* Erase sector blocks */
1635 init_waitqueue_head(&wait_q);
1636 for (offset=cfe_offset;offset < cfe_offset+erasesize;offset += cfe_mtd->erasesize) {
1637 printk("cfe_commit: ERASE sector block offset(%08x) cfe_mtd->erasesize(%08x)\n", offset, cfe_mtd->erasesize);
1638 erase.mtd = cfe_mtd;
1639 erase.addr = offset;
1640 erase.len = cfe_mtd->erasesize;
1641 erase.callback = erase_callback;
1642 erase.priv = (u_long) &wait_q;
1644 set_current_state(TASK_INTERRUPTIBLE);
1645 add_wait_queue(&wait_q, &wait);
1646 /* Unlock sector blocks */
1647 if (cfe_mtd->unlock)
1648 cfe_mtd->unlock(cfe_mtd, offset, cfe_mtd->erasesize);
1650 if ((ret = cfe_mtd->erase(cfe_mtd, &erase))) {
1651 set_current_state(TASK_RUNNING);
1652 remove_wait_queue(&wait_q, &wait);
1653 printk("cfe_commit: erase error\n");
1654 ret = -EIO;
1655 goto done;
1658 /* Wait for erase to finish */
1659 schedule();
1660 remove_wait_queue(&wait_q, &wait);
1663 ret = cfe_mtd->write(cfe_mtd, cfe_offset, erasesize, &len, cfe_buf);
1664 printk("cfe_commit: MTD_WRITE cfe_offset(%08x) erasesize(%08x) len(%08x) ret(%08x)\n", cfe_offset, erasesize, len, ret);
1666 if (ret || len != erasesize) {
1667 printk("cfe_commit: write error\n");
1668 ret = -EIO;
1671 done:
1672 if (cfe_mtd != NULL)
1674 put_mtd_device(cfe_mtd);
1675 cfe_mtd=NULL;
1677 if(cfe_buf != NULL)
1679 kfree(cfe_buf);
1680 cfe_buf=NULL;
1682 //printk("commit: %d\n", ret);
1683 return ret;
1684 #endif
1686 #endif
1689 //#ifdef CFE_UPDATE
1690 #if 0
1691 void cfe_init(void)
1693 size_t erasesize, len;
1694 int i;
1696 /* Find associated MTD device */
1697 for (i = 0; i < MAX_MTD_DEVICES; i++) {
1698 cfe_mtd = get_mtd_device(NULL, i);
1699 if (cfe_mtd) {
1700 printk("CFE MTD: %x %s %x\n", i, cfe_mtd->name, cfe_mtd->size);
1701 if (!strcmp(cfe_mtd->name, "boot"))
1702 break;
1703 put_mtd_device(cfe_mtd);
1706 if (i >= MAX_MTD_DEVICES)
1708 printk("No CFE MTD\n");
1709 cfe_mtd = NULL;
1712 if(!cfe_mtd) goto fail;
1714 /* sector blocks to be erased and backup */
1715 erasesize = ROUNDUP(CFE_NVRAM_SPACE, cfe_mtd->erasesize);
1717 /* printk("block size %d\n", erasesize); */
1719 cfe_buf = kmalloc(erasesize, GFP_KERNEL);
1721 if(!cfe_buf)
1723 /* printk("No CFE Memory\n"); */
1724 goto fail;
1726 cfe_mtd->read(cfe_mtd, CFE_NVRAM_START, erasesize, &len, cfe_buf);
1728 /* find nvram header */
1729 for(i=0;i<len;i+=4)
1731 cfe_nvram_header=(struct nvram_header *)&cfe_buf[i];
1732 if (cfe_nvram_header->magic==NVRAM_MAGIC) break;
1735 bcm947xx_watchdog_disable(); /*disable watchdog as well */
1737 #if 0
1738 printf("read from nvram %d %s\n", i, cfe_buf);
1739 for(i=0;i<CFE_SPACE;i++)
1741 if(i%16) printk("\n");
1742 printk("%02x ", (unsigned char)cfe_buf[i]);
1744 #endif
1745 return;
1746 fail:
1747 if (cfe_mtd)
1749 put_mtd_device(cfe_mtd);
1750 cfe_mtd=NULL;
1752 if(cfe_buf)
1754 kfree(cfe_buf);
1755 cfe_buf=NULL;
1757 return;
1760 void cfe_update(const char *keyword, const char *value)
1762 unsigned long i, offset;
1763 struct nvram_header tmp, *header;
1764 uint8 crc;
1765 // int ret;
1766 int found = 0;
1768 if(!cfe_buf||!cfe_mtd)
1769 cfe_init();
1771 if (!cfe_buf||!cfe_mtd) return;
1773 header = cfe_nvram_header;
1775 printk("before: %x %x\n", header->len, cfe_nvram_header->crc_ver_init&0xff);
1777 for(i=CFE_NVRAM_START;i<=CFE_NVRAM_END;i++)
1779 if(strncmp(&cfe_buf[i], keyword, strlen(keyword))==0)
1781 printk("before: %s\n", cfe_buf+i);
1782 offset=strlen(keyword);
1783 memcpy(cfe_buf+i+offset+1, value, strlen(value));
1784 printk("after: %s\n", cfe_buf+i);
1785 found = 1;
1789 if(!found)
1791 char *tmp_buf = (char *)cfe_nvram_header;
1793 /* printk("header len: %x\n", header->len); */
1794 sprintf(tmp_buf+header->len, "%s=%s", keyword, value);
1795 header->len = header->len + strlen(keyword) + strlen(value) + 2;
1796 /* printk("header len: %x\n", header->len); */
1799 tmp.crc_ver_init = htol32(header->crc_ver_init);
1800 tmp.config_refresh = htol32(header->config_refresh);
1801 tmp.config_ncdl = htol32(header->config_ncdl);
1802 crc = hndcrc8((char *) &tmp + 9, sizeof(struct nvram_header) - 9, CRC8_INIT_VALUE);
1804 /* Continue CRC8 over data bytes */
1805 crc = hndcrc8((char *) &header[1], header->len - sizeof(struct nvram_header), crc);
1806 header->crc_ver_init = (header->crc_ver_init&0xFFFFFF00)|crc;
1807 printk("after: %x %x\n", header->crc_ver_init&0xFF, crc);
1810 int cfe_commit(void)
1812 DECLARE_WAITQUEUE(wait, current);
1813 wait_queue_head_t wait_q;
1814 struct erase_info erase;
1815 // unsigned int i;
1816 int ret;
1817 size_t erasesize, len;
1818 u_int32_t offset;
1819 // char *buf;
1821 if(!cfe_buf||!cfe_mtd) cfe_init();
1823 if(!cfe_mtd||!cfe_buf)
1825 ret = - ENOMEM;
1826 goto done;
1829 /* Backup sector blocks to be erased */
1830 erasesize = ROUNDUP(CFE_NVRAM_SPACE, cfe_mtd->erasesize);
1832 down(&nvram_sem);
1834 /* Erase sector blocks */
1835 init_waitqueue_head(&wait_q);
1838 for (offset=CFE_NVRAM_START;offset <= CFE_NVRAM_END;offset += cfe_mtd->erasesize) {
1839 erase.mtd = cfe_mtd;
1840 erase.addr = offset;
1841 erase.len = cfe_mtd->erasesize;
1842 erase.callback = erase_callback;
1843 erase.priv = (u_long) &wait_q;
1845 set_current_state(TASK_INTERRUPTIBLE);
1846 add_wait_queue(&wait_q, &wait);
1847 /* Unlock sector blocks */
1848 if (cfe_mtd->unlock)
1849 cfe_mtd->unlock(cfe_mtd, offset, cfe_mtd->erasesize);
1851 if ((ret = cfe_mtd->erase(cfe_mtd, &erase))) {
1852 set_current_state(TASK_RUNNING);
1853 remove_wait_queue(&wait_q, &wait);
1854 printk("cfe_commit: erase error\n");
1855 goto done;
1858 /* Wait for erase to finish */
1859 schedule();
1860 remove_wait_queue(&wait_q, &wait);
1863 ret = cfe_mtd->write(cfe_mtd, CFE_NVRAM_START, erasesize, &len, cfe_buf);
1864 /* printk("Write offset: %x %x %x\n", ret, len, erasesize); */
1866 if (ret || len != erasesize) {
1867 printk("cfe_commit: write error\n");
1868 ret = -EIO;
1871 done:
1872 up(&nvram_sem);
1873 if (cfe_mtd)
1875 put_mtd_device(cfe_mtd);
1876 cfe_mtd=NULL;
1878 if(cfe_buf)
1880 kfree(cfe_buf);
1881 cfe_buf=NULL;
1883 /* printk("commit: %d\n", ret); */
1884 return ret;
1887 #endif
1890 module_init(dev_nvram_init);
1891 module_exit(dev_nvram_exit);