Created
July 24, 2020 16:14
-
-
Save armarti/bd7582c587e6b62a09b1379444e410cf to your computer and use it in GitHub Desktop.
Small CLI utility for converting FreshTomato (and probably many other Tomato) .cfg backup files to readable nvram values
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Converted from https://bitbucket.org/pedro311/freshtomato-arm/raw/86fd29f5a23b1ab4b2dfb4bdae2a625fd3a134a9/release/src-rt-6.x.4708/router/nvram_arm/main.c | |
* which contained the following copyright. | |
*/ | |
/* | |
* Frontend command-line utility for Linux NVRAM layer | |
* | |
* Copyright (C) 2012, Broadcom Corporation. All Rights Reserved. | |
* | |
* Permission to use, copy, modify, and/or distribute this software for any | |
* purpose with or without fee is hereby granted, provided that the above | |
* copyright notice and this permission notice appear in all copies. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
* | |
* $Id: main.c 325698 2012-04-04 12:40:07Z $ | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#define MAX_NVRAM_SPACE 0x20000 | |
#define PROFILE_HEADER "HDR1" | |
#define PROFILE_HEADER_NEW "HDR2" | |
#define INFILE_NOT_READABLE -1 | |
#define OUTFILE_NOT_WRITABLE -2 | |
#define INVALID_CFG_FORMAT -3 | |
int nvram_restore_to_stdout(char * file); | |
int nvram_restore_to_file(char * file, char * outfile); | |
int nvram_restore_new(char * file, FILE * ofp); | |
int tell_error(int rv, char * infile, const char * outfile) { | |
switch(rv) { | |
case INFILE_NOT_READABLE: | |
fprintf(stderr, "Cannot read input file \"%s\"\n", infile); | |
return -1 * rv; | |
case OUTFILE_NOT_WRITABLE: | |
fprintf(stderr, "Cannot write to output file \"%s\"\n", outfile); | |
return -1 * rv; | |
case INVALID_CFG_FORMAT: | |
fprintf(stderr, "Invalid cfg file format for \"%s\"\n", infile); | |
return -1 * rv; | |
default: | |
fprintf(stderr, "Wrote %d bytes to ", rv); | |
fprintf(stderr, "%s\n", outfile); | |
return 0; | |
} | |
} | |
int main(int argc, char ** argv) { | |
char * progname = argv[0]; | |
if(argc < 2) { | |
fprintf(stderr, "Usage: %s <infile path> [outfile path]\n", progname); | |
return 1; | |
} | |
char *infile = argv[1]; | |
int rv; | |
if(argc > 2) { | |
char * outfile = argv[2]; | |
int rtn = nvram_restore_to_file(infile, outfile); | |
rv = tell_error(rtn, infile, (const char *)outfile); | |
} else { | |
int rtn = nvram_restore_to_stdout(infile); | |
rv = tell_error(rtn, infile, "stdout"); | |
} | |
return 0; | |
} | |
int nvram_restore_to_stdout(char * file) { | |
return nvram_restore_new(file, stdout); | |
} | |
int nvram_restore_to_file(char * file, char * outfile) { | |
FILE *ofp; | |
if((ofp = fopen(outfile, "w+")) == NULL) { | |
return OUTFILE_NOT_WRITABLE; | |
} | |
int rv = nvram_restore_new(file, ofp); | |
fclose(ofp); | |
return rv; | |
} | |
int nvram_restore_new(char * file, FILE * ofp) { | |
FILE *fp; | |
char header[8], *p, *v, buf[MAX_NVRAM_SPACE]; | |
unsigned long count, filelen, *filelenptr, i; | |
unsigned char rand, *randptr; | |
unsigned long nbytes = 0; | |
if((fp = fopen(file, "r+")) == NULL) { | |
return INFILE_NOT_READABLE; | |
} | |
count = fread(header, 1, 8, fp); | |
if(count>=8 && strncmp(header, PROFILE_HEADER, 4) == 0) { | |
filelenptr = (unsigned long *)(header + 4); | |
fread(buf, 1, *filelenptr, fp); | |
} else if(count>=8 && strncmp(header, PROFILE_HEADER_NEW, 4) == 0) { | |
filelenptr = (unsigned long *)(header + 4); | |
filelen = *filelenptr & 0xffffff; | |
randptr = (unsigned char *)(header + 7); | |
rand = *randptr; | |
count = fread(buf, 1, filelen, fp); | |
for(i = 0; i < count; i++) { | |
if((unsigned char) buf[i] > ( 0xfd - 0x1)) { | |
/* e.g.: to skip the case: 0x61 0x62 0x63 0x00 0x00 0x61 0x62 0x63 */ | |
if(i > 0 && buf[i-1] != 0x0) { | |
buf[i] = 0x0; | |
} | |
} else { | |
buf[i] = 0xff + rand - buf[i]; | |
} | |
} | |
} else { | |
fclose(fp); | |
return INVALID_CFG_FORMAT; | |
} | |
fclose(fp); | |
p = buf; | |
while(*p) { | |
// e.g.: to skip the case: 00 2e 30 2e 32 38 00 ff 77 61 6e | |
if(*p == '\0' || *p < 32 || *p > 127 ) { | |
p = p + 1; | |
continue; | |
} | |
v = strchr(p, '='); | |
if(v != NULL) { | |
*v++ = '\0'; | |
nbytes += fprintf(ofp, "%s", p); | |
nbytes += fprintf(ofp, "=%s\n", v); | |
p = v + strlen(v) + 1; | |
} else { | |
nbytes += fprintf(ofp, "%s=\n", p); | |
p = p + 1; | |
} | |
} | |
return nbytes; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment