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> |\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]));
122 static int show_main(int argc
, char **argv
)
125 char buffer
[NVRAM_SPACE
];
132 for (n
= 1; n
< argc
; ++n
) {
133 if (strcmp(argv
[n
], "--nostat") == 0) stat
= 0;
134 else if (strcmp(argv
[n
], "--nosort") == 0) sort
= 0;
139 system("nvram show --nostat --nosort | sort"); // smallest and easiest way :)
145 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) {
148 if (!isprint(*q
)) *q
= ' ';
155 n
= sizeof(struct nvram_header
) + (p
- buffer
);
156 printf("---\n%d entries, %d bytes used, %d bytes free.\n", count
, n
, NVRAM_SPACE
- n
);
161 static int find_main(int argc
, char **argv
)
166 snprintf(cmd
, sizeof(cmd
), "nvram show --nostat --nosort | sort | grep \"%s\"", argv
[1]);
168 return (r
== -1) ? 1 : WEXITSTATUS(r
);
171 static const char *nv_default_value(const defaults_t
*t
)
173 int model
= get_model();
175 if (strcmp(t
->key
, "wl_txpwr") == 0) {
188 else if (strcmp(t
->key
, "usb_enable") == 0) {
190 case MODEL_WRTSL54GS
:
193 case MODEL_WL500GPv2
:
201 case MODEL_WRT610Nv2
:
206 case MODEL_F5D8235v3
:
214 static void nv_fix_wl(const char *oldnv
, const char *newnv
)
218 if (nvram_get(wl_nvname(newnv
, 0, 0)) == NULL
) {
219 p
= nvram_get(oldnv
);
220 if (p
!= NULL
) nvram_set(wl_nvname(newnv
, -1, 0), p
);
225 static int validate_main(int argc
, char **argv
)
233 for (i
= 1; i
< argc
; ++i
) {
234 if (strcmp(argv
[i
], "--restore") == 0) {
237 else if (strncmp(argv
[i
], "--wl", 4) == 0) {
238 unit
= atoi(argv
[i
] + 4);
242 for (t
= defaults
; t
->key
; t
++) {
243 if (strncmp(t
->key
, "wl_", 3) == 0) {
245 p
= wl_nvname(t
->key
+ 3, unit
, 0);
246 if (force
|| nvram_get(p
) == NULL
)
247 nvram_set(p
, t
->value
);
253 static int defaults_main(int argc
, char **argv
)
262 if (strcmp(argv
[1], "--yes") == 0) {
265 else if (strcmp(argv
[1], "--initcheck") != 0) {
269 if ((!nvram_match("restore_defaults", "0")) || (!nvram_match("os_name", "linux"))) {
273 #if 0 // --need to test--
274 // prevent lockout if upgrading from DD-WRT v23 SP2+ w/ encrypted password
275 if (nvram_match("nvram_ver", "2")) {
276 nvram_unset("nvram_ver");
278 // If username is "", root or admin, then nvram_ver was probably a left-over
279 // from an old DD-WRT installation (ex: DD-WRT -> Linksys (reset) ->
280 // Tomato) and we don't need to do anything. Otherwise, reset.
281 if ((p
= nvram_get("httpd_username")) != NULL
) {
282 if ((*p
!= 0) && (strcmp(p
, "root") != 0) && (strcmp(p
, "admin") != 0)) {
283 nvram_unset("httpd_passwd");
284 nvram_unset("httpd_username"); // not used here, but dd will try to re-encrypt this
290 if (force
) nvram_unset("nvram_ver"); // prep to prevent problems later
293 // keep the compatibility with old security_mode2, wds_enable, mac_wl - removeme after 1/1/2012
294 nv_fix_wl("security_mode2", "security_mode");
295 nv_fix_wl("wds_enable", "wds_enable");
296 nv_fix_wl("mac_wl", "macaddr");
298 for (t
= defaults
; t
->key
; t
++) {
299 if (((p
= nvram_get(t
->key
)) == NULL
) || (force
)) {
300 if (t
->value
== NULL
) {
303 if (!force
) _dprintf("%s=%s is not the default (NULL) - resetting\n", t
->key
, p
);
308 nvram_set(t
->key
, nv_default_value(t
));
309 if (!force
) _dprintf("%s=%s is not the default (%s) - resetting\n", t
->key
, p
? p
: "(NULL)", nv_default_value(t
));
313 else if (strncmp(t
->key
, "wl_", 3) == 0) {
316 strcat(s
, t
->key
+ 3);
317 if (nvram_get(s
) == NULL
) nvram_set(s
, nvram_safe_get(t
->key
));
322 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) ||
323 (check_hw_type() == HW_BCM4712
)) t
= if_vlan
;
325 for (; t
->key
; t
++) {
326 if (((p
= nvram_get(t
->key
)) == NULL
) || (*p
== 0) || (force
)) {
327 nvram_set(t
->key
, t
->value
);
329 if (!force
) _dprintf("%s=%s is not the default (%s) - resetting\n", t
->key
, p
? p
: "(NULL)", t
->value
);
334 for (j
= 0; j
< 2; j
++) {
335 for (i
= 0; i
< 20; i
++) {
336 sprintf(s
, "wl%d_wds%d", j
, i
);
341 for (i
= 0; i
< LED_COUNT
; ++i
) {
342 sprintf(s
, "led_%s", led_names
[i
]);
347 for (i
= 1; i
< 50; i
++) {
348 sprintf(s
, "rrule%d", i
);
353 if (!nvram_match("boot_wait", "on")) {
354 nvram_set("boot_wait", "on");
358 nvram_set("os_name", "linux");
359 nvram_set("os_version", tomato_version
);
360 nvram_set("os_date", tomato_buildtime
);
362 if ((commit
) || (force
)) {
363 printf("Saving...\n");
367 printf("No change was necessary.\n");
372 static int commit_main(int argc
, char **argv
)
376 printf("Commit... ");
383 static int erase_main(int argc
, char **argv
)
385 printf("Erasing nvram...\n");
386 return eval("mtd-erase", "-d", "nvram");
390 * Find nvram param name; return pointer which should be treated as const
391 * return NULL if not found.
393 * NOTE: This routine special-cases the variable wl_bss_enabled. It will
394 * return the normal default value if asked for wl_ or wl0_. But it will
395 * return 0 if asked for a virtual BSS reference like wl0.1_.
397 static const char *get_default_value(const char *name
)
401 char fixed_name
[NVRAM_MAX_PARAM_LEN
+ 1];
403 if (strncmp(name
, "wl", 2) == 0 && isdigit(name
[2]) && ((p
= strchr(name
, '_'))))
404 snprintf(fixed_name
, sizeof(fixed_name
) - 1, "wl%s", p
);
406 strncpy(fixed_name
, name
, sizeof(fixed_name
));
408 if (strcmp(fixed_name
, "wl_bss_enabled") == 0) {
409 if (name
[3] == '.' || name
[4] == '.') /* Virtual interface */
413 for (t
= defaults
; t
->key
; t
++) {
414 if (strcmp(t
->key
, name
) == 0 || strcmp(t
->key
, fixed_name
) == 0)
415 return (t
->value
? : "");
426 static int export_main(int argc
, char **argv
)
429 char buffer
[NVRAM_SPACE
];
436 static const char *start
[4] = { "\"", "nvram set ", "{ \"", "" };
437 static const char *stop
[4] = { "\"", "\"", "\" },", "" };
444 for (n
= 1; n
< argc
; ++n
) {
445 if (strcmp(argv
[n
], "--nodefaults") == 0) {
446 if (argc
< 3) help();
453 if (strcmp(argv
[1], "--dump") == 0) {
455 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) {
460 if (strcmp(argv
[1], "--dump0") == 0) {
462 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) { }
463 fwrite(buffer
, p
- buffer
, 1, stdout
);
467 if (strcmp(argv
[1], "--c") == 0) mode
= X_C
;
468 else if (strcmp(argv
[1], "--set") == 0) mode
= X_SET
;
469 else if (strcmp(argv
[1], "--tab") == 0) mode
= X_TAB
;
470 else if (strcmp(argv
[1], "--quote") == 0) mode
= X_QUOTE
;
480 bv
= strchr(bk
, '=');
483 if ((v
= (char *)get_default_value(bk
)) != NULL
) {
484 skip
= (strcmp(bv
, v
) == 0);
494 printf("%s", start
[mode
]);
498 if (mode
== X_SET
) putchar(*p
);
502 if (mode
== X_SET
) putchar(*p
);
506 if (mode
== X_SET
) putchar(*p
);
515 if (mode
!= X_SET
) putchar(*p
);
519 if ((eq
== 0) && (mode
> X_QUOTE
)) {
520 printf((mode
== X_C
) ? "\", \"" :
521 ((mode
== X_SET
) ? "=\"" : "\t"));
527 if (!isprint(*p
)) printf("\\x%02x", *p
);
533 printf("%s\n", stop
[mode
]);
539 static int in_defaults(const char *key
)
544 for (t
= defaults
; t
->key
; t
++) {
545 if (strcmp(t
->key
, key
) == 0) return 1;
548 if ((strncmp(key
, "rrule", 5) == 0) && ((n
= atoi(key
+ 5)) > 0) && (n
< 50)) return 1;
553 static int import_main(int argc
, char **argv
)
564 if (strcmp(argv
[1], "--forceall") == 0) {
569 if ((f
= fopen(argv
[1], "r")) == NULL
) {
570 printf("Error opening file.\n");
574 same
= skip
= set
= 0;
576 while (fgets(s
, sizeof(s
), f
) != NULL
) {
578 while ((--n
> 0) && (isspace(s
[n
]))) ;
579 if ((n
<= 0) || (s
[n
] != '"')) continue;
583 while (isspace(*k
)) ++k
;
584 if (*k
!= '"') continue;
587 if ((v
= strchr(k
, '=')) == NULL
) continue;
609 printf("Error unescaping %s=%s\n", k
, v
);
620 if ((all
) || (in_defaults(k
))) {
621 if (nvram_match(k
, v
)) {
623 // printf("SAME: %s=%s\n", k, v);
627 printf("%s=%s\n", k
, v
);
633 // printf("SKIP: %s=%s\n", k, v);
639 printf("---\n%d skipped, %d same, %d set\n", skip
, same
, set
);
643 #define V1 0x31464354L
648 char buffer
[NVRAM_SPACE
];
651 static int backup_main(int argc
, char **argv
)
663 data
.hwid
= check_hw_type();
666 while (*p
!= 0) p
+= strlen(p
) + 1;
668 size
= (sizeof(data
) - sizeof(data
.buffer
)) + (p
- data
.buffer
) + 1;
670 strcpy(tmp
, "/tmp/nvramXXXXXX");
672 if (f_write(tmp
, &data
, size
, 0, 0) != size
) {
673 printf("Error saving file.\n");
676 sprintf(s
, "gzip < %s > %s", tmp
, argv
[1]);
682 printf("Error compressing file.\n");
690 static int restore_main(int argc
, char **argv
)
701 char current
[NVRAM_SPACE
];
714 for (i
= 1; i
< argc
; ++i
) {
715 if (argv
[i
][0] == '-') {
716 if (strcmp(argv
[i
], "--test") == 0) {
719 else if (strcmp(argv
[i
], "--force") == 0) {
722 else if (strcmp(argv
[i
], "--forceall") == 0) {
725 else if (strcmp(argv
[i
], "--nocommit") == 0) {
738 strcpy(tmp
, "/tmp/nvramXXXXXX");
740 sprintf(s
, "gzip -d < %s > %s", name
, tmp
);
741 if (system(s
) != 0) {
743 printf("Error decompressing file.\n");
748 if ((size
<= (sizeof(data
) - sizeof(data
.buffer
))) || (size
> sizeof(data
)) ||
749 (f_read(tmp
, &data
, sizeof(data
)) != size
)) {
751 printf("Invalid data size or read error.\n");
757 if (data
.sig
!= V1
) {
758 printf("Invalid signature: %08lX / %08lX\n", data
.sig
, V1
);
762 hw
= check_hw_type();
763 if ((data
.hwid
!= hw
) && (!force
)) {
764 printf("Invalid hardware type: %08lX / %08lX\n", data
.hwid
, hw
);
770 size
-= sizeof(data
) - sizeof(data
.buffer
);
771 if ((data
.buffer
[size
- 1] != 0) || (data
.buffer
[size
- 2] != 0)) {
773 printf("Corrupted data area.\n");
781 if ((bv
= strchr(bk
, '=')) == NULL
) {
785 if (strcmp(bk
, "et0macaddr") == 0) {
786 if (!nvram_match(bk
, bv
+ 1)) {
788 printf("Cannot restore on a different router.\n");
795 if (((b
- data
.buffer
) + 1) != size
) {
796 printf("Extra data found at the end.\n");
804 if (!wait_action_idle(10)) {
805 printf("System busy.\n");
808 set_action(ACT_SW_RESTORE
);
812 nset
= nunset
= nsame
= 0;
818 bv
= strchr(bk
, '=');
821 if ((force
!= 1) || (in_defaults(bk
))) {
822 if (!nvram_match(bk
, bv
)) {
823 if (test
) printf("nvram set \"%s=%s\"\n", bk
, bv
);
824 else nvram_set(bk
, bv
);
843 if ((cv
= strchr(ck
, '=')) == NULL
) {
844 printf("Invalid data in NVRAM: %s.", ck
);
849 if ((force
!= 1) || (in_defaults(ck
))) {
855 bv
= strchr(bk
, '=');
857 cmp
= strcmp(bk
, ck
);
863 if (test
) printf("nvram unset \"%s\"\n", ck
);
864 else nvram_unset(ck
);
870 if ((nset
== 0) && (nunset
== 0)) commit
= 0;
871 printf("\nPerformed %d set and %d unset operations. %d required no changes.\n%s\n",
872 nset
, nunset
, nsame
, commit
? "Committing..." : "Not commiting.");
876 set_action(ACT_IDLE
);
877 if (commit
) nvram_commit();
883 static int test_main(int argc
, char **argv
)
886 static const char *extra[] = {
887 "clkfreq", "pa0b0", "pa0b1", "pa0b2", "pa0itssit", "pa0maxpwr",
888 "sdram_config", "sdram_init", "sdram_ncdl", "vlan0ports", NULL };
891 char buffer
[NVRAM_SPACE
];
893 const defaults_t
*rest
;
894 struct nvram_convert
*conv
;
896 printf("Unknown keys:\n");
901 e
= k
+ strlen(k
) + 1;
902 if ((v
= strchr(k
, '=')) != NULL
) {
904 for (rest
= defaults
; rest
->key
; ++rest
) {
905 if (strcmp(k
, rest
->key
) == 0) break;
907 if (rest
->key
== NULL
) {
908 for (conv
= nvram_converts
; conv
->name
; ++conv
) {
909 if ((strcmp(k
, conv
->name
) == 0) || (strcmp(k
, conv
->wl0_name
) == 0)) break;
911 if (conv
->name
== NULL
) {
912 printf("%s=%s\n", k
, v
+ 1);
914 for (x = extra; *x; ++x) {
915 if (strcmp(k, *x) == 0) break;
918 printf("nvram unset \"%s\"\n", k);
925 printf("WARNING: '%s' doesn't have a '=' delimiter\n", k
);
935 static int setfb64_main(int argc
, char **argv
)
937 if (!nvram_set_file(argv
[1], argv
[2], 10240)) {
938 fprintf(stderr
, "Unable to set %s or read %s\n", argv
[1], argv
[2]);
944 static int getfb64_main(int argc
, char **argv
)
946 if (!nvram_get_file(argv
[1], argv
[2], 10240)) {
947 fprintf(stderr
, "Unable to get %s or write %s\n", argv
[1], argv
[2]);
953 // -----------------------------------------------------------------------------
958 int (*main
)(int argc
, char *argv
[]);
961 static const applets_t applets
[] = {
962 { "set", 3, set_main
},
963 { "get", 3, get_main
},
964 { "unset", 3, unset_main
},
965 { "ren", 4, ren_main
},
966 { "show", -2, show_main
},
967 { "commit", 2, commit_main
},
968 { "erase", 2, erase_main
},
969 { "find", 3, find_main
},
970 { "export", -3, export_main
},
971 { "import", -3, import_main
},
972 { "defaults", 3, defaults_main
},
973 { "validate", -3, validate_main
},
974 { "backup", 3, backup_main
},
975 { "restore", -3, restore_main
},
976 { "setfb64", 4, setfb64_main
},
977 { "getfb64", 4, getfb64_main
},
978 { "setfile", 4, f2n_main
},
979 { "getfile", 4, n2f_main
},
980 { "setfile2nvram", 3, save2f_main
},
981 // { "test", 2, test_main },
985 int main(int argc
, char **argv
)
992 if (strcmp(argv
[1], a
->name
) == 0) {
993 if ((argc
!= a
->args
) && ((a
->args
> 0) || (argc
< -(a
->args
)))) help();
994 return a
->main(argc
- 1, argv
+ 1);