4 Copyright (C) 2006-2009 Jonathan Zarate
21 #include "nvram_convert.h"
25 __attribute__ ((noreturn
))
26 static void help(void)
30 "Copyright (C) 2006-2009 Jonathan Zarate\n\n"
31 "Usage: nvram set <key=value> | get <key> | unset <key> | default_get <key> [only work on K26AC routers]\n"
32 "ren <key> <key> | commit | erase | show [--nosort|--nostat] |\n"
33 "find <text> | defaults <--yes|--initcheck> | backup <filename> |\n"
34 "restore <filename> [--test] [--force] [--forceall] [--nocommit] |\n"
35 "export <--quote|--c|--set|--tab> [--nodefaults] |\n"
36 "export <--dump|--dump0> | import [--forceall] <filename> |\n"
37 "setfb64 <key> <filename> | getfb64 <key> <filename> |\n"
38 "setfile <key> <filename> | getfile <key> <filename> | setfile2nvram <filename>"
44 static void getall(char *buffer
)
46 if (nvram_getall(buffer
, NVRAM_SPACE
) != 0) {
47 fprintf(stderr
, "Error reading NVRAM\n");
52 static int set_main(int argc
, char **argv
)
56 if ((b
= strdup(argv
[1])) == NULL
) {
57 fprintf(stderr
, "Not enough memory");
60 if ((p
= strchr(b
, '=')) != NULL
) {
68 static int get_main(int argc
, char **argv
)
72 if ((p
= nvram_get(argv
[1])) != NULL
) {
79 static int unset_main(int argc
, char **argv
)
85 static int ren_main(int argc
, char **argv
)
89 if ((p
= nvram_get(argv
[1])) == NULL
) {
90 fprintf(stderr
, "Unable to find %s\n", argv
[1]);
93 if (strcmp(argv
[1], argv
[2]) != 0) {
94 nvram_set(argv
[2], p
);
100 extern int nvram_file2nvram(const char *name
, const char *filename
);
101 extern int nvram_nvram2file(const char *name
, const char *filename
);
103 static int f2n_main(int argc
, char **argv
)
105 return (nvram_file2nvram(argv
[1], argv
[2]));
109 static int n2f_main(int argc
, char **argv
)
111 return (nvram_nvram2file(argv
[1], argv
[2]));
114 static int save2f_main(int argc
, char **argv
)
116 char name
[128] = "FILE:";
118 strcpy(name
+5, argv
[1]);
119 return (nvram_file2nvram(name
, argv
[1]));
121 static int default_get_main(int argc
, char **argv
){
125 if ((p
= nvram_default_get(argv
[1])) != NULL
) {
132 static int show_main(int argc
, char **argv
)
135 char buffer
[NVRAM_SPACE
];
142 for (n
= 1; n
< argc
; ++n
) {
143 if (strcmp(argv
[n
], "--nostat") == 0) stat
= 0;
144 else if (strcmp(argv
[n
], "--nosort") == 0) sort
= 0;
149 system("nvram show --nostat --nosort | sort"); // smallest and easiest way :)
155 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) {
158 if (!isprint(*q
)) *q
= ' ';
165 n
= sizeof(struct nvram_header
) + (p
- buffer
);
166 printf("---\n%d entries, %d bytes used, %d bytes free.\n", count
, n
, NVRAM_SPACE
- n
);
171 static int find_main(int argc
, char **argv
)
176 snprintf(cmd
, sizeof(cmd
), "nvram show --nostat --nosort | sort | grep \"%s\"", argv
[1]);
178 return (r
== -1) ? 1 : WEXITSTATUS(r
);
181 static const char *nv_default_value(const defaults_t
*t
)
183 int model
= get_model();
185 if (strcmp(t
->key
, "wl_txpwr") == 0) {
198 else if (strcmp(t
->key
, "usb_enable") == 0) {
200 case MODEL_WRTSL54GS
:
203 case MODEL_WL500GPv2
:
211 case MODEL_WRT610Nv2
:
216 case MODEL_F5D8235v3
:
224 static void nv_fix_wl(const char *oldnv
, const char *newnv
)
228 if (nvram_get(wl_nvname(newnv
, 0, 0)) == NULL
) {
229 p
= nvram_get(oldnv
);
230 if (p
!= NULL
) nvram_set(wl_nvname(newnv
, -1, 0), p
);
235 static int validate_main(int argc
, char **argv
)
243 for (i
= 1; i
< argc
; ++i
) {
244 if (strcmp(argv
[i
], "--restore") == 0) {
247 else if (strncmp(argv
[i
], "--wl", 4) == 0) {
248 unit
= atoi(argv
[i
] + 4);
252 for (t
= defaults
; t
->key
; t
++) {
253 if (strncmp(t
->key
, "wl_", 3) == 0) {
255 p
= wl_nvname(t
->key
+ 3, unit
, 0);
256 if (force
|| nvram_get(p
) == NULL
)
257 nvram_set(p
, t
->value
);
263 static int defaults_main(int argc
, char **argv
)
272 if (strcmp(argv
[1], "--yes") == 0) {
275 else if (strcmp(argv
[1], "--initcheck") != 0) {
279 if ((!nvram_match("restore_defaults", "0")) || (!nvram_match("os_name", "linux"))) {
283 #if 0 // --need to test--
284 // prevent lockout if upgrading from DD-WRT v23 SP2+ w/ encrypted password
285 if (nvram_match("nvram_ver", "2")) {
286 nvram_unset("nvram_ver");
288 // If username is "", root or admin, then nvram_ver was probably a left-over
289 // from an old DD-WRT installation (ex: DD-WRT -> Linksys (reset) ->
290 // Tomato) and we don't need to do anything. Otherwise, reset.
291 if ((p
= nvram_get("httpd_username")) != NULL
) {
292 if ((*p
!= 0) && (strcmp(p
, "root") != 0) && (strcmp(p
, "admin") != 0)) {
293 nvram_unset("httpd_passwd");
294 nvram_unset("httpd_username"); // not used here, but dd will try to re-encrypt this
300 if (force
) nvram_unset("nvram_ver"); // prep to prevent problems later
303 // keep the compatibility with old security_mode2, wds_enable, mac_wl - removeme after 1/1/2012
304 nv_fix_wl("security_mode2", "security_mode");
305 nv_fix_wl("wds_enable", "wds_enable");
306 nv_fix_wl("mac_wl", "macaddr");
308 for (t
= defaults
; t
->key
; t
++) {
309 if (((p
= nvram_get(t
->key
)) == NULL
) || (force
)) {
310 if (t
->value
== NULL
) {
313 if (!force
) _dprintf("%s=%s is not the default (NULL) - resetting\n", t
->key
, p
);
318 nvram_set(t
->key
, nv_default_value(t
));
319 if (!force
) _dprintf("%s=%s is not the default (%s) - resetting\n", t
->key
, p
? p
: "(NULL)", nv_default_value(t
));
323 else if (strncmp(t
->key
, "wl_", 3) == 0) {
326 strcat(s
, t
->key
+ 3);
327 if (nvram_get(s
) == NULL
) nvram_set(s
, nvram_safe_get(t
->key
));
332 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) ||
333 (check_hw_type() == HW_BCM4712
)) t
= if_vlan
;
335 for (; t
->key
; t
++) {
336 if (((p
= nvram_get(t
->key
)) == NULL
) || (*p
== 0) || (force
)) {
337 nvram_set(t
->key
, t
->value
);
339 if (!force
) _dprintf("%s=%s is not the default (%s) - resetting\n", t
->key
, p
? p
: "(NULL)", t
->value
);
344 for (j
= 0; j
< 2; j
++) {
345 for (i
= 0; i
< 20; i
++) {
346 sprintf(s
, "wl%d_wds%d", j
, i
);
351 for (i
= 0; i
< LED_COUNT
; ++i
) {
352 sprintf(s
, "led_%s", led_names
[i
]);
357 for (i
= 1; i
< 50; i
++) {
358 sprintf(s
, "rrule%d", i
);
363 if (!nvram_match("boot_wait", "on")) {
364 nvram_set("boot_wait", "on");
368 nvram_set("os_name", "linux");
369 nvram_set("os_version", tomato_version
);
370 nvram_set("os_date", tomato_buildtime
);
372 if ((commit
) || (force
)) {
373 printf("Saving...\n");
377 printf("No change was necessary.\n");
382 static int commit_main(int argc
, char **argv
)
386 printf("Commit... ");
393 static int erase_main(int argc
, char **argv
)
395 printf("Erasing nvram...\n");
396 return eval("mtd-erase", "-d", "nvram");
400 * Find nvram param name; return pointer which should be treated as const
401 * return NULL if not found.
403 * NOTE: This routine special-cases the variable wl_bss_enabled. It will
404 * return the normal default value if asked for wl_ or wl0_. But it will
405 * return 0 if asked for a virtual BSS reference like wl0.1_.
407 static const char *get_default_value(const char *name
)
411 char fixed_name
[NVRAM_MAX_PARAM_LEN
+ 1];
413 if (strncmp(name
, "wl", 2) == 0 && isdigit(name
[2]) && ((p
= strchr(name
, '_'))))
414 snprintf(fixed_name
, sizeof(fixed_name
) - 1, "wl%s", p
);
416 strncpy(fixed_name
, name
, sizeof(fixed_name
));
418 if (strcmp(fixed_name
, "wl_bss_enabled") == 0) {
419 if (name
[3] == '.' || name
[4] == '.') /* Virtual interface */
423 for (t
= defaults
; t
->key
; t
++) {
424 if (strcmp(t
->key
, name
) == 0 || strcmp(t
->key
, fixed_name
) == 0)
425 return (t
->value
? : "");
436 static int export_main(int argc
, char **argv
)
439 char buffer
[NVRAM_SPACE
];
446 static const char *start
[4] = { "\"", "nvram set ", "{ \"", "" };
447 static const char *stop
[4] = { "\"", "\"", "\" },", "" };
454 for (n
= 1; n
< argc
; ++n
) {
455 if (strcmp(argv
[n
], "--nodefaults") == 0) {
456 if (argc
< 3) help();
463 if (strcmp(argv
[1], "--dump") == 0) {
465 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) {
470 if (strcmp(argv
[1], "--dump0") == 0) {
472 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) { }
473 fwrite(buffer
, p
- buffer
, 1, stdout
);
477 if (strcmp(argv
[1], "--c") == 0) mode
= X_C
;
478 else if (strcmp(argv
[1], "--set") == 0) mode
= X_SET
;
479 else if (strcmp(argv
[1], "--tab") == 0) mode
= X_TAB
;
480 else if (strcmp(argv
[1], "--quote") == 0) mode
= X_QUOTE
;
490 bv
= strchr(bk
, '=');
493 if ((v
= (char *)get_default_value(bk
)) != NULL
) {
494 skip
= (strcmp(bv
, v
) == 0);
504 printf("%s", start
[mode
]);
508 if (mode
== X_SET
) putchar(*p
);
512 if (mode
== X_SET
) putchar(*p
);
516 if (mode
== X_SET
) putchar(*p
);
525 if (mode
!= X_SET
) putchar(*p
);
526 else printf("\\%c", *p
);
529 if ((eq
== 0) && (mode
> X_QUOTE
)) {
530 printf((mode
== X_C
) ? "\", \"" :
531 ((mode
== X_SET
) ? "=\"" : "\t"));
537 if (!isprint(*p
)) printf("\\x%02x", *p
);
543 printf("%s\n", stop
[mode
]);
549 static int in_defaults(const char *key
)
554 for (t
= defaults
; t
->key
; t
++) {
555 if (strcmp(t
->key
, key
) == 0) return 1;
558 if ((strncmp(key
, "rrule", 5) == 0) && ((n
= atoi(key
+ 5)) > 0) && (n
< 50)) return 1;
563 static int import_main(int argc
, char **argv
)
574 if (strcmp(argv
[1], "--forceall") == 0) {
579 if ((f
= fopen(argv
[1], "r")) == NULL
) {
580 printf("Error opening file.\n");
584 same
= skip
= set
= 0;
586 while (fgets(s
, sizeof(s
), f
) != NULL
) {
588 while ((--n
> 0) && (isspace(s
[n
]))) ;
589 if ((n
<= 0) || (s
[n
] != '"')) continue;
593 while (isspace(*k
)) ++k
;
594 if (*k
!= '"') continue;
597 if ((v
= strchr(k
, '=')) == NULL
) continue;
619 printf("Error unescaping %s=%s\n", k
, v
);
630 if ((all
) || (in_defaults(k
))) {
631 if (nvram_match(k
, v
)) {
633 // printf("SAME: %s=%s\n", k, v);
637 printf("%s=%s\n", k
, v
);
643 // printf("SKIP: %s=%s\n", k, v);
649 printf("---\n%d skipped, %d same, %d set\n", skip
, same
, set
);
653 #define V1 0x31464354L
658 char buffer
[NVRAM_SPACE
];
661 static int backup_main(int argc
, char **argv
)
673 data
.hwid
= check_hw_type();
676 while (*p
!= 0) p
+= strlen(p
) + 1;
678 size
= (sizeof(data
) - sizeof(data
.buffer
)) + (p
- data
.buffer
) + 1;
680 strcpy(tmp
, "/tmp/nvramXXXXXX");
682 if (f_write(tmp
, &data
, size
, 0, 0) != size
) {
683 printf("Error saving file.\n");
686 sprintf(s
, "gzip < %s > %s", tmp
, argv
[1]);
692 printf("Error compressing file.\n");
700 static int restore_main(int argc
, char **argv
)
711 char current
[NVRAM_SPACE
];
724 for (i
= 1; i
< argc
; ++i
) {
725 if (argv
[i
][0] == '-') {
726 if (strcmp(argv
[i
], "--test") == 0) {
729 else if (strcmp(argv
[i
], "--force") == 0) {
732 else if (strcmp(argv
[i
], "--forceall") == 0) {
735 else if (strcmp(argv
[i
], "--nocommit") == 0) {
748 strcpy(tmp
, "/tmp/nvramXXXXXX");
750 sprintf(s
, "gzip -d < %s > %s", name
, tmp
);
751 if (system(s
) != 0) {
753 printf("Error decompressing file.\n");
758 if ((size
<= (sizeof(data
) - sizeof(data
.buffer
))) || (size
> sizeof(data
)) ||
759 (f_read(tmp
, &data
, sizeof(data
)) != size
)) {
761 printf("Invalid data size or read error.\n");
767 if (data
.sig
!= V1
) {
768 printf("Invalid signature: %08lX / %08lX\n", data
.sig
, V1
);
772 hw
= check_hw_type();
773 if ((data
.hwid
!= hw
) && (!force
)) {
774 printf("Invalid hardware type: %08lX / %08lX\n", data
.hwid
, hw
);
780 size
-= sizeof(data
) - sizeof(data
.buffer
);
781 if ((data
.buffer
[size
- 1] != 0) || (data
.buffer
[size
- 2] != 0)) {
783 printf("Corrupted data area.\n");
791 if ((bv
= strchr(bk
, '=')) == NULL
) {
795 if (strcmp(bk
, "et0macaddr") == 0) {
796 if (!nvram_match(bk
, bv
+ 1)) {
798 printf("Cannot restore on a different router.\n");
805 if (((b
- data
.buffer
) + 1) != size
) {
806 printf("Extra data found at the end.\n");
814 if (!wait_action_idle(10)) {
815 printf("System busy.\n");
818 set_action(ACT_SW_RESTORE
);
822 nset
= nunset
= nsame
= 0;
828 bv
= strchr(bk
, '=');
831 if ((force
!= 1) || (in_defaults(bk
))) {
832 if (!nvram_match(bk
, bv
)) {
833 if (test
) printf("nvram set \"%s=%s\"\n", bk
, bv
);
834 else nvram_set(bk
, bv
);
853 if ((cv
= strchr(ck
, '=')) == NULL
) {
854 printf("Invalid data in NVRAM: %s.", ck
);
859 if ((force
!= 1) || (in_defaults(ck
))) {
865 bv
= strchr(bk
, '=');
867 cmp
= strcmp(bk
, ck
);
873 if (test
) printf("nvram unset \"%s\"\n", ck
);
874 else nvram_unset(ck
);
880 if ((nset
== 0) && (nunset
== 0)) commit
= 0;
881 printf("\nPerformed %d set and %d unset operations. %d required no changes.\n%s\n",
882 nset
, nunset
, nsame
, commit
? "Committing..." : "Not commiting.");
886 set_action(ACT_IDLE
);
887 if (commit
) nvram_commit();
893 static int test_main(int argc
, char **argv
)
896 static const char *extra[] = {
897 "clkfreq", "pa0b0", "pa0b1", "pa0b2", "pa0itssit", "pa0maxpwr",
898 "sdram_config", "sdram_init", "sdram_ncdl", "vlan0ports", NULL };
901 char buffer
[NVRAM_SPACE
];
903 const defaults_t
*rest
;
904 struct nvram_convert
*conv
;
906 printf("Unknown keys:\n");
911 e
= k
+ strlen(k
) + 1;
912 if ((v
= strchr(k
, '=')) != NULL
) {
914 for (rest
= defaults
; rest
->key
; ++rest
) {
915 if (strcmp(k
, rest
->key
) == 0) break;
917 if (rest
->key
== NULL
) {
918 for (conv
= nvram_converts
; conv
->name
; ++conv
) {
919 if ((strcmp(k
, conv
->name
) == 0) || (strcmp(k
, conv
->wl0_name
) == 0)) break;
921 if (conv
->name
== NULL
) {
922 printf("%s=%s\n", k
, v
+ 1);
924 for (x = extra; *x; ++x) {
925 if (strcmp(k, *x) == 0) break;
928 printf("nvram unset \"%s\"\n", k);
935 printf("WARNING: '%s' doesn't have a '=' delimiter\n", k
);
945 static int setfb64_main(int argc
, char **argv
)
947 if (!nvram_set_file(argv
[1], argv
[2], 10240)) {
948 fprintf(stderr
, "Unable to set %s or read %s\n", argv
[1], argv
[2]);
954 static int getfb64_main(int argc
, char **argv
)
956 if (!nvram_get_file(argv
[1], argv
[2], 10240)) {
957 fprintf(stderr
, "Unable to get %s or write %s\n", argv
[1], argv
[2]);
963 // -----------------------------------------------------------------------------
968 int (*main
)(int argc
, char *argv
[]);
971 static const applets_t applets
[] = {
972 { "set", 3, set_main
},
973 { "get", 3, get_main
},
974 { "unset", 3, unset_main
},
975 { "ren", 4, ren_main
},
976 { "show", -2, show_main
},
977 { "commit", 2, commit_main
},
978 { "erase", 2, erase_main
},
979 { "find", 3, find_main
},
980 { "export", -3, export_main
},
981 { "import", -3, import_main
},
982 { "defaults", 3, defaults_main
},
983 { "validate", -3, validate_main
},
984 { "backup", 3, backup_main
},
985 { "restore", -3, restore_main
},
986 { "setfb64", 4, setfb64_main
},
987 { "getfb64", 4, getfb64_main
},
988 { "setfile", 4, f2n_main
},
989 { "getfile", 4, n2f_main
},
990 { "setfile2nvram", 3, save2f_main
},
991 { "default_get", 3, default_get_main
},
992 // { "test", 2, test_main },
996 int main(int argc
, char **argv
)
1003 if (strcmp(argv
[1], a
->name
) == 0) {
1004 if ((argc
!= a
->args
) && ((a
->args
> 0) || (argc
< -(a
->args
)))) help();
1005 return a
->main(argc
- 1, argv
+ 1);