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
:
209 static void nv_fix_wl(const char *oldnv
, const char *newnv
)
213 if (nvram_get(wl_nvname(newnv
, 0, 0)) == NULL
) {
214 p
= nvram_get(oldnv
);
215 if (p
!= NULL
) nvram_set(wl_nvname(newnv
, -1, 0), p
);
220 static int validate_main(int argc
, char **argv
)
228 for (i
= 1; i
< argc
; ++i
) {
229 if (strcmp(argv
[i
], "--restore") == 0) {
232 else if (strncmp(argv
[i
], "--wl", 4) == 0) {
233 unit
= atoi(argv
[i
] + 4);
237 for (t
= defaults
; t
->key
; t
++) {
238 if (strncmp(t
->key
, "wl_", 3) == 0) {
240 p
= wl_nvname(t
->key
+ 3, unit
, 0);
241 if (force
|| nvram_get(p
) == NULL
)
242 nvram_set(p
, t
->value
);
248 static int defaults_main(int argc
, char **argv
)
257 if (strcmp(argv
[1], "--yes") == 0) {
260 else if (strcmp(argv
[1], "--initcheck") != 0) {
264 if ((!nvram_match("restore_defaults", "0")) || (!nvram_match("os_name", "linux"))) {
268 #if 0 // --need to test--
269 // prevent lockout if upgrading from DD-WRT v23 SP2+ w/ encrypted password
270 if (nvram_match("nvram_ver", "2")) {
271 nvram_unset("nvram_ver");
273 // If username is "", root or admin, then nvram_ver was probably a left-over
274 // from an old DD-WRT installation (ex: DD-WRT -> Linksys (reset) ->
275 // Tomato) and we don't need to do anything. Otherwise, reset.
276 if ((p
= nvram_get("httpd_username")) != NULL
) {
277 if ((*p
!= 0) && (strcmp(p
, "root") != 0) && (strcmp(p
, "admin") != 0)) {
278 nvram_unset("httpd_passwd");
279 nvram_unset("httpd_username"); // not used here, but dd will try to re-encrypt this
285 if (force
) nvram_unset("nvram_ver"); // prep to prevent problems later
288 // keep the compatibility with old security_mode2, wds_enable, mac_wl - removeme after 1/1/2012
289 nv_fix_wl("security_mode2", "security_mode");
290 nv_fix_wl("wds_enable", "wds_enable");
291 nv_fix_wl("mac_wl", "macaddr");
293 for (t
= defaults
; t
->key
; t
++) {
294 if (((p
= nvram_get(t
->key
)) == NULL
) || (force
)) {
295 if (t
->value
== NULL
) {
298 if (!force
) _dprintf("%s=%s is not the default (NULL) - resetting\n", t
->key
, p
);
303 nvram_set(t
->key
, nv_default_value(t
));
304 if (!force
) _dprintf("%s=%s is not the default (%s) - resetting\n", t
->key
, p
? p
: "(NULL)", nv_default_value(t
));
308 else if (strncmp(t
->key
, "wl_", 3) == 0) {
311 strcat(s
, t
->key
+ 3);
312 if (nvram_get(s
) == NULL
) nvram_set(s
, nvram_safe_get(t
->key
));
317 if ((strtoul(nvram_safe_get("boardflags"), NULL
, 0) & BFL_ENETVLAN
) ||
318 (check_hw_type() == HW_BCM4712
)) t
= if_vlan
;
320 for (; t
->key
; t
++) {
321 if (((p
= nvram_get(t
->key
)) == NULL
) || (*p
== 0) || (force
)) {
322 nvram_set(t
->key
, t
->value
);
324 if (!force
) _dprintf("%s=%s is not the default (%s) - resetting\n", t
->key
, p
? p
: "(NULL)", t
->value
);
329 for (j
= 0; j
< 2; j
++) {
330 for (i
= 0; i
< 20; i
++) {
331 sprintf(s
, "wl%d_wds%d", j
, i
);
336 for (i
= 0; i
< LED_COUNT
; ++i
) {
337 sprintf(s
, "led_%s", led_names
[i
]);
342 for (i
= 1; i
< 50; i
++) {
343 sprintf(s
, "rrule%d", i
);
348 if (!nvram_match("boot_wait", "on")) {
349 nvram_set("boot_wait", "on");
353 nvram_set("os_name", "linux");
354 nvram_set("os_version", tomato_version
);
355 nvram_set("os_date", tomato_buildtime
);
357 if ((commit
) || (force
)) {
358 printf("Saving...\n");
362 printf("No change was necessary.\n");
367 static int commit_main(int argc
, char **argv
)
371 printf("Commit... ");
378 static int erase_main(int argc
, char **argv
)
380 printf("Erasing nvram...\n");
381 return eval("mtd-erase", "-d", "nvram");
385 * Find nvram param name; return pointer which should be treated as const
386 * return NULL if not found.
388 * NOTE: This routine special-cases the variable wl_bss_enabled. It will
389 * return the normal default value if asked for wl_ or wl0_. But it will
390 * return 0 if asked for a virtual BSS reference like wl0.1_.
392 static const char *get_default_value(const char *name
)
396 char fixed_name
[NVRAM_MAX_PARAM_LEN
+ 1];
398 if (strncmp(name
, "wl", 2) == 0 && isdigit(name
[2]) && ((p
= strchr(name
, '_'))))
399 snprintf(fixed_name
, sizeof(fixed_name
) - 1, "wl%s", p
);
401 strncpy(fixed_name
, name
, sizeof(fixed_name
));
403 if (strcmp(fixed_name
, "wl_bss_enabled") == 0) {
404 if (name
[3] == '.' || name
[4] == '.') /* Virtual interface */
408 for (t
= defaults
; t
->key
; t
++) {
409 if (strcmp(t
->key
, name
) == 0 || strcmp(t
->key
, fixed_name
) == 0)
410 return (t
->value
? : "");
421 static int export_main(int argc
, char **argv
)
424 char buffer
[NVRAM_SPACE
];
431 static const char *start
[4] = { "\"", "nvram set ", "{ \"", "" };
432 static const char *stop
[4] = { "\"", "\"", "\" },", "" };
439 for (n
= 1; n
< argc
; ++n
) {
440 if (strcmp(argv
[n
], "--nodefaults") == 0) {
441 if (argc
< 3) help();
448 if (strcmp(argv
[1], "--dump") == 0) {
450 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) {
455 if (strcmp(argv
[1], "--dump0") == 0) {
457 for (p
= buffer
; *p
; p
+= strlen(p
) + 1) { }
458 fwrite(buffer
, p
- buffer
, 1, stdout
);
462 if (strcmp(argv
[1], "--c") == 0) mode
= X_C
;
463 else if (strcmp(argv
[1], "--set") == 0) mode
= X_SET
;
464 else if (strcmp(argv
[1], "--tab") == 0) mode
= X_TAB
;
465 else if (strcmp(argv
[1], "--quote") == 0) mode
= X_QUOTE
;
475 bv
= strchr(bk
, '=');
478 if ((v
= (char *)get_default_value(bk
)) != NULL
) {
479 skip
= (strcmp(bv
, v
) == 0);
489 printf("%s", start
[mode
]);
493 if (mode
== X_SET
) putchar(*p
);
497 if (mode
== X_SET
) putchar(*p
);
501 if (mode
== X_SET
) putchar(*p
);
510 if (mode
!= X_SET
) putchar(*p
);
514 if ((eq
== 0) && (mode
> X_QUOTE
)) {
515 printf((mode
== X_C
) ? "\", \"" :
516 ((mode
== X_SET
) ? "=\"" : "\t"));
522 if (!isprint(*p
)) printf("\\x%02x", *p
);
528 printf("%s\n", stop
[mode
]);
534 static int in_defaults(const char *key
)
539 for (t
= defaults
; t
->key
; t
++) {
540 if (strcmp(t
->key
, key
) == 0) return 1;
543 if ((strncmp(key
, "rrule", 5) == 0) && ((n
= atoi(key
+ 5)) > 0) && (n
< 50)) return 1;
548 static int import_main(int argc
, char **argv
)
559 if (strcmp(argv
[1], "--forceall") == 0) {
564 if ((f
= fopen(argv
[1], "r")) == NULL
) {
565 printf("Error opening file.\n");
569 same
= skip
= set
= 0;
571 while (fgets(s
, sizeof(s
), f
) != NULL
) {
573 while ((--n
> 0) && (isspace(s
[n
]))) ;
574 if ((n
<= 0) || (s
[n
] != '"')) continue;
578 while (isspace(*k
)) ++k
;
579 if (*k
!= '"') continue;
582 if ((v
= strchr(k
, '=')) == NULL
) continue;
604 printf("Error unescaping %s=%s\n", k
, v
);
615 if ((all
) || (in_defaults(k
))) {
616 if (nvram_match(k
, v
)) {
618 // printf("SAME: %s=%s\n", k, v);
622 printf("%s=%s\n", k
, v
);
628 // printf("SKIP: %s=%s\n", k, v);
634 printf("---\n%d skipped, %d same, %d set\n", skip
, same
, set
);
638 #define V1 0x31464354L
643 char buffer
[NVRAM_SPACE
];
646 static int backup_main(int argc
, char **argv
)
658 data
.hwid
= check_hw_type();
661 while (*p
!= 0) p
+= strlen(p
) + 1;
663 size
= (sizeof(data
) - sizeof(data
.buffer
)) + (p
- data
.buffer
) + 1;
665 strcpy(tmp
, "/tmp/nvramXXXXXX");
667 if (f_write(tmp
, &data
, size
, 0, 0) != size
) {
668 printf("Error saving file.\n");
671 sprintf(s
, "gzip < %s > %s", tmp
, argv
[1]);
677 printf("Error compressing file.\n");
685 static int restore_main(int argc
, char **argv
)
696 char current
[NVRAM_SPACE
];
709 for (i
= 1; i
< argc
; ++i
) {
710 if (argv
[i
][0] == '-') {
711 if (strcmp(argv
[i
], "--test") == 0) {
714 else if (strcmp(argv
[i
], "--force") == 0) {
717 else if (strcmp(argv
[i
], "--forceall") == 0) {
720 else if (strcmp(argv
[i
], "--nocommit") == 0) {
733 strcpy(tmp
, "/tmp/nvramXXXXXX");
735 sprintf(s
, "gzip -d < %s > %s", name
, tmp
);
736 if (system(s
) != 0) {
738 printf("Error decompressing file.\n");
743 if ((size
<= (sizeof(data
) - sizeof(data
.buffer
))) || (size
> sizeof(data
)) ||
744 (f_read(tmp
, &data
, sizeof(data
)) != size
)) {
746 printf("Invalid data size or read error.\n");
752 if (data
.sig
!= V1
) {
753 printf("Invalid signature: %08lX / %08lX\n", data
.sig
, V1
);
757 hw
= check_hw_type();
758 if ((data
.hwid
!= hw
) && (!force
)) {
759 printf("Invalid hardware type: %08lX / %08lX\n", data
.hwid
, hw
);
765 size
-= sizeof(data
) - sizeof(data
.buffer
);
766 if ((data
.buffer
[size
- 1] != 0) || (data
.buffer
[size
- 2] != 0)) {
768 printf("Corrupted data area.\n");
776 if ((bv
= strchr(bk
, '=')) == NULL
) {
780 if (strcmp(bk
, "et0macaddr") == 0) {
781 if (!nvram_match(bk
, bv
+ 1)) {
783 printf("Cannot restore on a different router.\n");
790 if (((b
- data
.buffer
) + 1) != size
) {
791 printf("Extra data found at the end.\n");
799 if (!wait_action_idle(10)) {
800 printf("System busy.\n");
803 set_action(ACT_SW_RESTORE
);
807 nset
= nunset
= nsame
= 0;
813 bv
= strchr(bk
, '=');
816 if ((force
!= 1) || (in_defaults(bk
))) {
817 if (!nvram_match(bk
, bv
)) {
818 if (test
) printf("nvram set \"%s=%s\"\n", bk
, bv
);
819 else nvram_set(bk
, bv
);
838 if ((cv
= strchr(ck
, '=')) == NULL
) {
839 printf("Invalid data in NVRAM: %s.", ck
);
844 if ((force
!= 1) || (in_defaults(ck
))) {
850 bv
= strchr(bk
, '=');
852 cmp
= strcmp(bk
, ck
);
858 if (test
) printf("nvram unset \"%s\"\n", ck
);
859 else nvram_unset(ck
);
865 if ((nset
== 0) && (nunset
== 0)) commit
= 0;
866 printf("\nPerformed %d set and %d unset operations. %d required no changes.\n%s\n",
867 nset
, nunset
, nsame
, commit
? "Committing..." : "Not commiting.");
871 set_action(ACT_IDLE
);
872 if (commit
) nvram_commit();
878 static int test_main(int argc
, char **argv
)
881 static const char *extra[] = {
882 "clkfreq", "pa0b0", "pa0b1", "pa0b2", "pa0itssit", "pa0maxpwr",
883 "sdram_config", "sdram_init", "sdram_ncdl", "vlan0ports", NULL };
886 char buffer
[NVRAM_SPACE
];
888 const defaults_t
*rest
;
889 struct nvram_convert
*conv
;
891 printf("Unknown keys:\n");
896 e
= k
+ strlen(k
) + 1;
897 if ((v
= strchr(k
, '=')) != NULL
) {
899 for (rest
= defaults
; rest
->key
; ++rest
) {
900 if (strcmp(k
, rest
->key
) == 0) break;
902 if (rest
->key
== NULL
) {
903 for (conv
= nvram_converts
; conv
->name
; ++conv
) {
904 if ((strcmp(k
, conv
->name
) == 0) || (strcmp(k
, conv
->wl0_name
) == 0)) break;
906 if (conv
->name
== NULL
) {
907 printf("%s=%s\n", k
, v
+ 1);
909 for (x = extra; *x; ++x) {
910 if (strcmp(k, *x) == 0) break;
913 printf("nvram unset \"%s\"\n", k);
920 printf("WARNING: '%s' doesn't have a '=' delimiter\n", k
);
930 static int setfb64_main(int argc
, char **argv
)
932 if (!nvram_set_file(argv
[1], argv
[2], 10240)) {
933 fprintf(stderr
, "Unable to set %s or read %s\n", argv
[1], argv
[2]);
939 static int getfb64_main(int argc
, char **argv
)
941 if (!nvram_get_file(argv
[1], argv
[2], 10240)) {
942 fprintf(stderr
, "Unable to get %s or write %s\n", argv
[1], argv
[2]);
948 // -----------------------------------------------------------------------------
953 int (*main
)(int argc
, char *argv
[]);
956 static const applets_t applets
[] = {
957 { "set", 3, set_main
},
958 { "get", 3, get_main
},
959 { "unset", 3, unset_main
},
960 { "ren", 4, ren_main
},
961 { "show", -2, show_main
},
962 { "commit", 2, commit_main
},
963 { "erase", 2, erase_main
},
964 { "find", 3, find_main
},
965 { "export", -3, export_main
},
966 { "import", -3, import_main
},
967 { "defaults", 3, defaults_main
},
968 { "validate", -3, validate_main
},
969 { "backup", 3, backup_main
},
970 { "restore", -3, restore_main
},
971 { "setfb64", 4, setfb64_main
},
972 { "getfb64", 4, getfb64_main
},
973 { "setfile", 4, f2n_main
},
974 { "getfile", 4, n2f_main
},
975 { "setfile2nvram", 3, save2f_main
},
976 // { "test", 2, test_main },
980 int main(int argc
, char **argv
)
987 if (strcmp(argv
[1], a
->name
) == 0) {
988 if ((argc
!= a
->args
) && ((a
->args
> 0) || (argc
< -(a
->args
)))) help();
989 return a
->main(argc
- 1, argv
+ 1);