⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tvixfw.c

📁 TViX firmware creation tool.
💻 C
字号:
/*   Copyright (C) 2008 Petter Wahlman, aka BadEIP   Tvixfw is free software: you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation, either version 3 of the License, or   (at your option) any later version.   Tvixfw is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with Tvixfw.  If not, see <http://www.gnu.org/licenses/>.   usage:      tvixfw --dump     /path/to/firmware.fwp      tvixfw --create   /path/to/fwp.header   */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <dirent.h>#include <libgen.h>#include <errno.h>#include <getopt.h>#include <unistd.h>#include <time.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#include <tvixfw.h>#define DECRYPTED_FILE  "fwp.decrypted"#define HEADER_FILE     "fwp.header"#define OPT_DUMP        1#define OPT_CREATE      2typedef struct fs_info {   u32 avail;   u32 data;   u32 size;} __attribute__((packed)) fs_info_t;typedef struct tvix_header {   unsigned char unknown[0xc]; // string   unsigned char version;   unsigned char version_major;   unsigned char version_minor;   unsigned char unkown1[0x9];   unsigned char model[16];   u32 unknown2;   u32 rel_date;   fs_info_t fs[MAX_FILESYSTEMS];   u32 file_len;} __attribute__((packed)) tvix_header_t;char *fs_name[] = {   "disabled0",   "disabled1",   "disabled2",   "romfs.rootfs",   "disabled3",   "jffs2.apps",   "jffs2.fonts",   "disabled4",   "disabled5",   "disabled6"};static int dump_data(char *filename, void *data, u32 size){   int fd, n;   int rc = 1;   fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);   if (-1 == fd) {      perror(filename);      return rc;   }   n = write(fd, data, size);   if (n == size)      rc = 0;   close(fd);   return rc;}static int dump_filesystems(unsigned char *unc, tvix_header_t *th){   int i, fdd[MAX_FILESYSTEMS];   int rc = 1;   memset(fdd, 0, sizeof(fdd));   for (i = 0; i < MAX_FILESYSTEMS; i++) {      if (!th->fs[i].avail)         continue;      //("fs[%d] writing 0x%08lx (%lu) bytes\n", i, th->fs[i].size, th->fs[i].size);      rc |= fdd[i] = dump_data(fs_name[i], unc + th->fs[i].data, th->fs[i].size);   }   return rc;   }static void print_header(tvix_header_t *th){   int i;   struct tm *t;   printf("%s\n", th->model);   t = gmtime((time_t *)&th->rel_date);   printf("%u.%u.%u (%d/%d-%d %.2d:%.2d)\n",          th->version, th->version_major, th->version_minor,         t->tm_mday, t->tm_mon +1, t->tm_year + 1900,         t->tm_hour, t->tm_min);/* rather verbose, but I tend to build often */   printf("firmware size: %u\n", th->file_len);      for (i = 0; i < MAX_FILESYSTEMS; i++) {      if (th->fs[i].avail) {         printf("fs[%d] data: 0x%08x size: 0x%08x name: \"%s\"\n",             i, th->fs[i].data, th->fs[i].size, fs_name[i]);      }   }   putchar('\n');   return;}void foo(void){   printf("foo\n");}// --dumpstatic int opt_dump(int fd){   unsigned char *decrypted;   int rc = 1;   do {      tvix_header_t th;      unsigned char *unc;      u32 unc_size = 0;      struct stat st;      if (fstat(fd, &st)) {         fprintf(stderr, "fstat: could not get size assosiated with fd: %d\n", fd);         return rc;      }         decrypted = malloc(st.st_size + 1024);      if (!decrypted) {         perror("malloc");         return rc;      }      read(fd, decrypted, st.st_size);      memcpy(&th, decrypted, sizeof(th));      print_header(&th);      if ((rc = dump_data(HEADER_FILE, &th, sizeof(th))))         break;      decrypt(decrypted + sizeof(th), st.st_size - sizeof(th));      if ((rc = zlib_uncompress(&unc, &unc_size, decrypted + sizeof(th), st.st_size - sizeof(th)))) {         fprintf(stderr, "error, zlib_uncompress: %d\n", rc);         break;      }      if ((rc = dump_data(DECRYPTED_FILE, unc, unc_size)))         break;      if ((rc = dump_filesystems(unc, &th)))         break;   } while(0);   free(decrypted);   return rc;}// --createstatic int opt_create(int fd){   unsigned char *decrypted;   unsigned char *encrypted;   u32 crc = 0;   char firmware_file[64];   tvix_header_t th;   struct dirent *dp;   struct stat st;   u32 enc_len;   int i, n, fdd, fdf;   DIR *dirp;   int rc = 1;   read(fd, &th, sizeof(th));   print_header(&th);   fdd = open(DECRYPTED_FILE, O_RDWR);   if (-1 == fdd) {      fprintf(stderr, "error, unable to locate %s.\n", DECRYPTED_FILE);      return rc;   }   fstat(fdd, &st);   decrypted = malloc(st.st_size);   if (!decrypted) {      perror("malloc");      return rc;   }   // sigh...   read(fdd, decrypted, st.st_size);   close(fdd);   if ((dirp = opendir(".")) == NULL) {      perror("error, couldn't open '.'");      return rc;   }   while ((dp = readdir(dirp))) {      for (i = 0; i < MAX_FILESYSTEMS; i++) {         if (!th.fs[i].avail)            continue;         if (!strcmp(dp->d_name, fs_name[i])) {            u32 align;            struct stat tst;            int tfd;            printf("injecting: %s\n", fs_name[i]);            tfd = open(dp->d_name, O_RDONLY);            if (-1 == tfd) {               perror(dp->d_name);               break;            }            fstat(tfd, &tst);            // st.st_size = fucked            n = read(tfd, &decrypted[th.fs[i].data], tst.st_size);            close(tfd);            align = ALIGN_DATA(tst.st_size);            printf("- original size:     0x%08x\n"                   "- modified size:     0x%08x %s\n"                   "- new size (aligned) 0x%08x\n",               th.fs[i].size,                (u32)tst.st_size,                th.fs[i].size != tst.st_size ? "[size changed]" : "", align);             if (align != th.fs[i].size)                th.fs[i].size = align;            //printf("- %d bytes written\n\n", n);         }      }   }   closedir(dirp);   rc = zlib_compress(&encrypted, &enc_len, decrypted, st.st_size);   if (rc) {      fprintf(stderr, "error, zlib_compress: %d\n", rc);      return rc;   }   rc = encrypt(encrypted, enc_len);   if (rc) {      fprintf(stderr, "error, encrypt: %d\n", rc);      return rc;   }   th.rel_date = time(NULL);   th.file_len = sizeof(th) + enc_len + 4;   printf("new firmware size: %u\n", th.file_len);   calc_crc((unsigned char *)&th, sizeof(th), &crc);   calc_crc(encrypted, enc_len, &crc);   snprintf(firmware_file, sizeof(firmware_file), "BadEIP_M-6x00_%d.%d.%d.fwp", th.version, th.version_major, th.version_minor);   fdf = open(firmware_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);   if (-1 == fdf) {      perror(firmware_file);      return rc;   }      write(fdf, &th, sizeof(th));   write(fdf, encrypted, enc_len);   write(fdf, &crc, sizeof(crc));   close(fdf);   if (!rc)      printf("\n\"firmware created: %s\n", firmware_file);   return rc;}static void print_usage(void){   printf("usage: tvixfw [option]\n"                  "--dump   firmware.fwp   dump contents of \"firmware.fwp\"\n"                  "--create firmware.fwp   create firmware from dumped \"firmware.fwp\"\n"                  "\n"   );   exit(1);}int main(int argc, char **argv){   char *source;   char dir[256];   int opt, fd;   int rc;   printf("tvixfw v.%s. (c) Petter Wahlman, aka BadEIP\n\n", TVIXFW_VERSION);   opt = 0;   while (1) {      int c;      int option_ndex = 0;      static struct option long_ptions[] = {         {"dump",   0, 0, 'd' },         {"create", 0, 0, 'c' },         {0,        0, 0,  0  }      };      c = getopt_long(argc,  argv, "dc", long_ptions, &option_ndex);      if (-1 == c)         break;      switch (c) {         case 'd':            opt = OPT_DUMP;            break;         case 'c':            opt = OPT_CREATE;            break;         default:            print_usage();      }   }   if (!opt)      print_usage();   source = argv[optind++];   if (!source) {      fprintf(stderr, "error, no source file specified\n");      return 1;   }   if (opt == OPT_DUMP) {      sprintf(dir, "%s.dump", basename(source));      mkdir(dir, 0755);   } else {      if (!strstr(source, "fwp.header")) {         fprintf(stderr, "error, source must refer to fwp.header\n");         return 1;      }      strcpy(dir, source);      *(char *)(strrchr(dir, '/')) = '\0';   }   fd = open(source, O_RDONLY);   if (-1 == fd) {      perror(source);      return 1;   }   chdir(dir);   if (opt == OPT_DUMP)      rc = opt_dump(fd);   else      rc = opt_create(fd);   close(fd);   printf("data saved in: \"./%s/\"\n", dir);   //printf("firmware generated.\n");   chdir(dir);   return rc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -