Skip navigation.
Home
Welcome to the home on the web of Hnr Kordewiner

belky.c

  1. /*
  2.  * Copyright (C) 2004-2005
  3.  * "Ian (Larry) Latter" <ian dot latter at midnightcode dot org>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13.  * General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18.  */
  19.  
  20. /*
  21.  * January 29, 2005 - v0.5
  22.  *
  23.  * Tool exended to support original openwrt trx tool functionality.
  24.  * OMG ... this code needs a rethink .. but not tonight josephine ..
  25.  *
  26.  */
  27.  
  28. /*
  29.  * January 26, 2005 - v0.4
  30.  *
  31.  * Tool exended to support extraction of kernel, file system and
  32.  * nvram vars from image. This version was never published.
  33.  *
  34.  */
  35.  
  36. /*
  37.  * October 10, 2004 - v0.3
  38.  *
  39.  * This "belky" tool is a hacked addition to OpenWRT's "trx" tool
  40.  * (as at July 29, 2004) which in itself is a hacked replacement for
  41.  * the 'trx' utility used to create wrt54g .trx firmware files. It
  42.  * isn't pretty, but ... you know ...
  43.  *
  44.  * -- Adapted from "trx" by Manuel Novoa III of August 2004
  45.  *
  46.  */
  47.  
  48. /*
  49.  * Nb: what was never made clear was that this file had been written
  50.  * to compile cleanly under Visual Studio - to build a native
  51.  * win32 binary. Fortunately, this was not ever needed to be
  52.  * used, however, the hooks have been left in place for someone
  53.  * more adventurous.
  54.  *
  55.  */
  56.  
  57. /*
  58.  * Compile;
  59.  *
  60.  * touch stdafx.h
  61.  * cc belky.c -o belky
  62.  * # or; make belky
  63.  *
  64.  */
  65.  
  66.  
  67. /* linux makefile should touch stdafx.h .. Visual Studio blows */
  68.  
  69. #include "stdafx.h"
  70.  
  71. #include <stdio.h>
  72. #include <stdlib.h>
  73. #include <stddef.h>
  74. #include <stdint.h>
  75. #include <string.h>
  76. #include <errno.h>
  77. #include <unistd.h>
  78. #include <endian.h>
  79. #include <byteswap.h>
  80. #include <fcntl.h>
  81. #include <sys/types.h>
  82. #include <sys/stat.h>
  83. #define O_BINARY 0
  84.  
  85. #if __BYTE_ORDER == __BIG_ENDIAN
  86. #define STORE32_LE(X) bswap_32(X)
  87. #define PULL32_LE(X) bswap_32(X)
  88. #elif __BYTE_ORDER == __LITTLE_ENDIAN
  89. #define STORE32_LE(X) (X)
  90. #define PULL32_LE(X) (X)
  91. #else
  92. #error unkown endianness!
  93. #endif
  94.  
  95. uint32_t crc32buf(char *buf, size_t len);
  96.  
  97.  
  98. /**********************************************************************/
  99.  
  100. /* Program Info */
  101. char vernam[32] = "belky";
  102. char vernum[6] = "0.5";
  103.  
  104. /* Type codes */
  105. int TYPE_TRX = 1;
  106. int TYPE_EXTENDED = 2;
  107.  
  108. /* home-made goodies .. */
  109. #define BELKY_MAGIC_H 0x44414F4C /* "LOAD" */
  110. #define TRX_MAGIC 0x30524448 /* "HDR0" */
  111. #define BELKY_MAGIC_F 0x5241564E /* "NVAR" */
  112.  
  113. // Seems the Header Version is wrong .. hmmm
  114. #define BELKY_VERS_H 0x00000800 /* Version Magic */
  115. #define TRX_VERSION 1
  116. #define BELKY_VERS_F 0x00008000 /* Version Magic */
  117. #define BELKY_MAX_LEN 0x3A0000
  118.  
  119.  
  120. struct belky_header {
  121. uint32_t magic; /* 0 ... 3 "LOAD" */
  122. uint32_t len; /* 4 ... 7 Length of file including header */
  123. uint32_t crc32; /* 8 ... 11 32-bit CRC (ver to eof), LE, !bit */
  124. uint32_t version; /* 12 ... 27 0x8000 (32bit LE), 0, 0, 0 */
  125. uint32_t pad_0;
  126. uint32_t pad_1;
  127. uint32_t pad_2;
  128. };
  129.  
  130. struct belky_header *header;
  131.  
  132.  
  133. struct trx_header {
  134. uint32_t magic; /* "HDR0" */
  135. uint32_t len; /* Length of file including header */
  136. uint32_t crc32; /* 32-bit CRC from flag_version to end of file */
  137. uint32_t flag_version; /* 0:15 flags, 16:31 version */
  138. uint32_t offsets[3]; /* Partition offsets from start of header */
  139. };
  140.  
  141. struct trx_header *theader;
  142.  
  143.  
  144. struct belky_footer {
  145. uint32_t magic; /* 0 ... 3 "NVAR" */
  146. uint32_t len; /* 4 ... 7 Length of footer including magic */
  147. uint32_t crc32; /* 8 ... 11 32-bit CRC (ver to eof), LE */
  148. uint32_t version; /* 12 ... 27 0x8000 (32bit LE), 0, 0, 0 */
  149. uint32_t pad_0;
  150. uint32_t pad_1;
  151. uint32_t pad_2;
  152. };
  153.  
  154. struct belky_footer *footer;
  155.  
  156.  
  157. /* Transient program global variables */
  158. uint32_t action_type;
  159. uint32_t fs_count;
  160. uint32_t config_create;
  161. uint32_t config_extract;
  162. uint32_t config_maxlen;
  163. char config_kernel[256];
  164. char config_fs0[256];
  165. char config_fs1[256];
  166. char config_fs2[256];
  167. char config_trx[256];
  168. char config_output[256];
  169. char config_userconf[256];
  170.  
  171. /* disabling this allows assumptions to be made, RE user request */
  172. int allow_dumb_defaults = 0;
  173.  
  174. /**********************************************************************/
  175.  
  176. int
  177. input_validation(void) {
  178. /* action (create/extractg) check */
  179. if (config_extract == 0 && config_create == 0) {
  180. printf("%s: no action (create or extract) specified "
  181. "(try --help).\n", vernam);
  182. return -1;
  183. }
  184. if (config_extract > 0 && config_create > 0) {
  185. printf("%s: two actions (create and extract) specified "
  186. "(try --help).\n", vernam);
  187. return -1;
  188. }
  189.  
  190. /* output file check */
  191. if (strlen(config_output) == 0 && action_type == TYPE_EXTENDED) {
  192. if (allow_dumb_defaults) {
  193. strncpy(config_output, "firmware.belkin", 255);
  194. } else {
  195. printf("%s: no output file specified "
  196. "(try --help).\n", vernam);
  197. return -1;
  198. }
  199. }
  200.  
  201. /* OpenWRT firmware file check */
  202. if (strlen(config_trx) == 0) {
  203. if (allow_dumb_defaults) {
  204. strncpy(config_trx, "linux.trx", 255);
  205. }
  206. if (strlen(config_kernel) == 0 || strlen(config_fs0) ==0) {
  207. printf("%s: no trx, and no alternative (kernel or "
  208. "filesystem) files specified (try --help).\n",
  209. vernam);
  210. return -1;
  211. }
  212. }
  213.  
  214. /* user.conf file check */
  215. if (strlen(config_userconf) == 0 && action_type == TYPE_EXTENDED) {
  216. if (allow_dumb_defaults) {
  217. strncpy(config_userconf, "user.conf", 255);
  218. }
  219. if (strlen(config_trx) == 0) {
  220. printf("%s: no trx or user.conf file specified "
  221. "(try --help).\n", vernam);
  222. return -1;
  223. }
  224. }
  225.  
  226. /* filesystem stacking check */
  227. if (strlen(config_fs1) != 0 && strlen(config_fs0) == 0) {
  228. printf("%s: fs1 specified without fs0 (?) "
  229. "(try --help).\n", vernam);
  230. return -1;
  231. }
  232. /*
  233. if (strlen(config_fs2) != 0 && strlen(config_fs0) == 0) {
  234. printf("%s: fs2 specified without fs0 (?) "
  235. "(try --help).\n", vernam);
  236. return -1;
  237. }
  238. if (strlen(config_fs2) != 0 && strlen(config_fs1) == 0) {
  239. printf("%s: fs2 specified without fs1 (?) "
  240. "(try --help).\n", vernam);
  241. return -1;
  242. }
  243. */
  244. if (strlen(config_fs0) != 0)
  245. fs_count++;
  246. if (strlen(config_fs1) != 0)
  247. fs_count++;
  248. /*
  249. if (strlen(config_fs2) != 0)
  250. fs_count++;
  251. */
  252.  
  253. /* action and pre-reqs check */
  254. if (action_type == TYPE_TRX &&
  255. (strlen(config_kernel) == 0 || fs_count == 0)) {
  256. printf("%s: TRX requested, but kernel or file system "
  257. "parameter is missing (try --help).\n", vernam);
  258. return -1;
  259. }
  260.  
  261.  
  262. /* maxlen check */
  263. if (config_maxlen > BELKY_MAX_LEN) {
  264. printf("%s: *warning* maxlen [%u] exceeds default maximum "
  265. " [%u]\n", vernam, config_maxlen, BELKY_MAX_LEN);
  266. printf("%s: Be very careful, you may overwrite NVRAM\n",
  267. vernam);
  268. } else {
  269. config_maxlen = BELKY_MAX_LEN;
  270. }
  271.  
  272.  
  273. return 0;
  274. }
  275.  
  276.  
  277. int
  278. read_in_data_file(char * data_file, void * buffer, int maxbytes, int type) {
  279. int fd;
  280. int bytes;
  281. char filesize[3];
  282.  
  283. bytes = 0;
  284. if (maxbytes < 0) {
  285. printf("%s: spare buffer space is negative -- "
  286. "increase maxlen (?)\n", vernam);
  287. return -1;
  288. }
  289.  
  290. if ((fd = open(data_file, O_BINARY | O_RDONLY )) < 0) {
  291. printf("%s: unable to open file [%s] for reading.\n",
  292. vernam, data_file);
  293. return -1;
  294. }
  295.  
  296. if(lseek(fd, 0, SEEK_SET) < 0) {
  297. printf("%s: unable to seek to start of file [%s]\n",
  298. vernam, data_file);
  299. return -1;
  300. }
  301.  
  302. /* special work for user.conf file */
  303. if (type == 2) {
  304. memset(filesize, 0, 3);
  305. bytes = read(fd, filesize, 2);
  306. if (bytes < 0) {
  307. printf("%s: unable to read from user.conf file [%s].\n",
  308. vernam, data_file);
  309. return -1;
  310. }
  311. bytes = (uint8_t)filesize[1] * 256 + (uint8_t)filesize[0];
  312. if (bytes > 0) {
  313. if ((bytes - 18) <= maxbytes) {
  314. maxbytes = bytes - 18;
  315. } else {
  316. printf("%s: more data in file [%s] than space "
  317. "left in buffer -- increase maxlen?\n",
  318. vernam, data_file);
  319. return -1;
  320. }
  321. } else {
  322. printf("%s: unable to read file size from header of "
  323. "file [%s].\n", vernam, data_file);
  324. return -1;
  325. }
  326. }
  327.  
  328. bytes = read(fd, buffer, maxbytes);
  329. close(fd);
  330. if(bytes < 0) {
  331. printf("%s: unable to read from file [%s].\n",
  332. vernam, data_file);
  333. return -1;
  334. }
  335.  
  336. return bytes;
  337. }
  338.  
  339.  
  340. int
  341. write_out_data_file(char * data_file, void * buffer, int maxbytes, int type) {
  342. int fd;
  343. int bytes;
  344. char filesize[3];
  345.  
  346.  
  347. if (maxbytes <= 0) {
  348. printf("%s: embedded file to be written had corrupt "
  349. "length (?)\n", vernam);
  350. return -1;
  351. }
  352.  
  353. if ((fd = open(data_file, O_BINARY | O_RDWR | O_CREAT | O_TRUNC,
  354. S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) < 0) {
  355. printf("%s: unable to open file [%s] for writing.\n",
  356. vernam, data_file);
  357. return -1;
  358. }
  359.  
  360. bytes = write(fd, buffer, maxbytes);
  361. close(fd);
  362. if(bytes <= 0) {
  363. printf("%s: unable to write to file [%s].\n",
  364. vernam, data_file);
  365. return -1;
  366. }
  367.  
  368. return bytes;
  369. }
  370.  
  371.  
  372. int
  373. write_firmware(char * data_file, char * buffer, int maxbytes) {
  374. int fd;
  375.  
  376. if ((fd = open(data_file, O_BINARY | O_RDWR | O_CREAT | O_TRUNC,
  377. S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) < 0) {
  378. printf("%s: unable to open firmware file [%s] for writing.\n",
  379. vernam, data_file);
  380. return -1;
  381. }
  382.  
  383. if (write(fd, buffer, maxbytes) <= 0) {
  384. printf("%s: unable to write to firmware file [%s].\n",
  385. vernam, data_file);
  386. return -1;
  387. }
  388.  
  389. close(fd);
  390.  
  391. return 0;
  392. }
  393.  
  394.  
  395. int
  396. fill_headers(uint32_t filelen, uint32_t trxlen, uint32_t footerlen, int ft) {
  397.  
  398. if (ft == 0) {
  399. theader->magic = STORE32_LE(TRX_MAGIC);
  400. theader->flag_version = STORE32_LE((TRX_VERSION << 16));
  401. theader->crc32 = crc32buf((char *) &theader->flag_version,
  402. trxlen -
  403. offsetof(struct trx_header, flag_version));
  404. theader->crc32 = STORE32_LE(theader->crc32);
  405. theader->len = STORE32_LE(trxlen);
  406. }
  407.  
  408. if (action_type == TYPE_TRX)
  409. return 0;
  410.  
  411. footer->magic = STORE32_LE(BELKY_MAGIC_F);
  412. footer->version = STORE32_LE(BELKY_VERS_F);
  413. footer->crc32 = crc32buf((char *) &footer->version,
  414. footerlen - offsetof(struct belky_footer, version));
  415. footer->crc32 = STORE32_LE(footer->crc32);
  416. footer->len = STORE32_LE(footerlen);
  417.  
  418. // Seems the Header Version is wrong .. hmmm
  419. header->magic = STORE32_LE(BELKY_MAGIC_H);
  420. header->version = STORE32_LE(BELKY_VERS_F);
  421. header->crc32 = crc32buf((char *) &header->version,
  422. filelen - offsetof(struct belky_header, version));
  423. header->crc32 = STORE32_LE(header->crc32);
  424. header->len = STORE32_LE(filelen);
  425.  
  426. return 0;
  427. }
  428.  
  429.  
  430. int
  431. write_debug(char * data_file, char * buffer, int maxbytes) {
  432. int fd;
  433.  
  434. if ((fd = open(data_file, O_BINARY | O_RDWR | O_CREAT | O_TRUNC ))
  435. < 0) {
  436. printf("%s: unable to open debug file [%s] for writing.\n",
  437. vernam, data_file);
  438. return -1;
  439. }
  440.  
  441. if (write(fd, buffer, maxbytes) <= 0) {
  442. printf("%s: unable to write to debug file [%s].\n",
  443. vernam, data_file);
  444. return -1;
  445. }
  446.  
  447. close(fd);
  448.  
  449. return 0;
  450. }
  451.  
  452.  
  453. int
  454. usage(int errlvl, char * runbin) {
  455. /* how many printf's must a man print out, before he is truly a man */
  456.  
  457. /*
  458. printf("%s: Usage;\n\n", vernam);
  459. printf(" Create;\n");
  460. printf(" %s -c[et] [-t {linux.trx}] [-u {user.conf}] "
  461. "[-e {firmware.belkin}] [-m maxlen]\n", runbin);
  462. printf("\n");
  463. printf(" Extract;\n");
  464. printf(" %s -x[et] [-t {linux.trx}] [-u {user.conf}] "
  465. "[-e {firmware.belkin}] [-m maxlen]\n", runbin);
  466. printf("\n\n");
  467. */
  468. printf("%s: Parameters;\n\n", vernam);
  469. printf(" Long Short Args Description\n");
  470. printf(" ~~~~~~~~~~ ~~~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
  471. "~~~~~~~~~~~~~~~~\n");
  472. printf(" --create[et] -ce|-ct Create [e]xtended or [t]rx "
  473. "type firmware\n");
  474. printf(" --exfirm -e {file} Use extended firmware file "
  475. "{file}\n");
  476. printf(" --filesystem0 -fs0 {file} Use file {file} as the first "
  477. "file system\n");
  478. printf(" --filesystem1 -fs1 {file} Use file {file} as the second "
  479. "file system\n");
  480. /*
  481. printf(" --filesystem2 -fs2 {file} Use file {file} as the third "
  482. "file system\n");
  483. */
  484. printf(" --help -h Display this help screen\n");
  485. printf(" --kernel -k {file} Use kernel file {file}\n");
  486. printf(" --maxlen -m {num} Over-ride / set firmware max "
  487. "length to {num}\n");
  488. printf(" --trx -t {file} Use OpenWRT (Broadcom) TRX "
  489. "firmware file {file}\n");
  490. printf(" --userconf -u {file} Use Belkin \"user.conf\" file "
  491. "{file}\n");
  492. printf(" --version -V Display version and exit\n");
  493. printf(" --extract[et] -xe|-xt Extract [e]xtended or [t]rx "
  494. "type firmware\n");
  495. printf("\n\n");
  496.  
  497. printf("%s: Example;\n\n", vernam);
  498. printf(" %s -xe -e F5D7230-4_x.bin "
  499. "-k kernel.bin -fs0 cramfs.bin -u nvram.txt\n", runbin);
  500. printf(" %s -ct -t linux.trx -k kernel.bin -fs0 cramfs.bin\n", runbin);
  501. printf("\n");
  502.  
  503. /* the answer, my friend, is exit number one ... */
  504. /* the answer is exit number one .. */
  505. exit(errlvl);
  506. }
  507.  
  508.  
  509. void
  510. parse_args(int argc, char** argv) {
  511. int argn;
  512.  
  513. /* defaults */
  514. action_type = 0;
  515. fs_count = 0;
  516. config_create = 0;
  517. config_extract = 0;
  518. config_maxlen = 0;
  519. memset(config_fs0, 0, 256);
  520. memset(config_fs1, 0, 256);
  521. memset(config_fs2, 0, 256);
  522. memset(config_kernel, 0, 256);
  523. memset(config_trx, 0, 256);
  524. memset(config_output, 0, 256);
  525. memset(config_userconf, 0, 256);
  526.  
  527. argn = 1;
  528. while (argn < argc && argv[argn][0] == '-') {
  529. // -ce, --createe
  530. if (strcmp(argv[argn], "-ce") == 0 ||
  531. strcmp(argv[argn], "--createe") == 0) {
  532. config_create = TYPE_EXTENDED;
  533. action_type = config_create;
  534. }
  535. // -ct, --createt
  536. else if (strcmp(argv[argn], "-ct") == 0 ||
  537. strcmp(argv[argn], "--createt") == 0) {
  538. config_create = TYPE_TRX;
  539. action_type = config_create;
  540. }
  541. // -e, --exfirm
  542. else if ((strcmp(argv[argn], "-e") == 0 ||
  543. strcmp(argv[argn], "--exfirm") == 0)
  544. && argn + 1 < argc) {
  545. ++argn;
  546. strncpy(config_output, argv[argn], 255);
  547. }
  548. // -fs0, --filesystem0
  549. else if ((strcmp(argv[argn], "-fs0") == 0 ||
  550. strcmp(argv[argn], "--filesystem0") == 0)
  551. && argn + 1 < argc) {
  552. ++argn;
  553. strncpy(config_fs0, argv[argn], 255);
  554. }
  555. // -fs1, --filesystem1
  556. else if ((strcmp(argv[argn], "-fs1") == 0 ||
  557. strcmp(argv[argn], "--filesystem1") == 0)
  558. && argn + 1 < argc) {
  559. ++argn;
  560. strncpy(config_fs1, argv[argn], 255);
  561. }
  562. // -fs2, --filesystem2
  563. /*
  564. else if ((strcmp(argv[argn], "-fs2") == 0 ||
  565. strcmp(argv[argn], "--filesystem2") == 0)
  566. && argn + 1 < argc) {
  567. ++argn;
  568. strncpy(config_fs2, argv[argn], 255);
  569. }
  570. */
  571. // -h, --help
  572. else if (strcmp(argv[argn], "-h") == 0 ||
  573. strcmp(argv[argn], "--help") == 0) {
  574. usage(0, argv[0]);
  575. }
  576. // -k, --kernel
  577. else if ((strcmp(argv[argn], "-k") == 0 ||
  578. strcmp(argv[argn], "--kernel") == 0)
  579. && argn + 1 < argc) {
  580. ++argn;
  581. strncpy(config_kernel, argv[argn], 255);
  582. }
  583. // -m, --maxlen
  584. else if ((strcmp(argv[argn], "-m") == 0 ||
  585. strcmp(argv[argn], "--maxlen") == 0)
  586. && argn + 1 < argc) {
  587. ++argn;
  588. config_maxlen = (uint32_t)atoi(argv[argn]);
  589. }
  590. // -t, --trx
  591. else if ((strcmp(argv[argn], "-t") == 0 ||
  592. strcmp(argv[argn], "--trx") == 0)
  593. && argn + 1 < argc) {
  594. ++argn;
  595. strncpy(config_trx, argv[argn], 255);
  596. }
  597. // -u, --userconf
  598. else if ((strcmp(argv[argn], "-u") == 0 ||
  599. strcmp(argv[argn], "--userconf") == 0)
  600. && argn + 1 < argc) {
  601. ++argn;
  602. strncpy(config_userconf, argv[argn], 255);
  603. }
  604. // -V, --version
  605. else if (strcmp(argv[argn], "-V") == 0 ||
  606. strcmp(argv[argn], "--version") == 0) {
  607. printf("%s v%s\n", vernam, vernum);
  608. exit(0);
  609. }
  610. // -xe, --extracte
  611. else if (strcmp(argv[argn], "-xe") == 0 ||
  612. strcmp(argv[argn], "--extracte") == 0) {
  613. config_extract = TYPE_EXTENDED;
  614. action_type = config_extract;
  615. }
  616. // -xt, --extractt
  617. else if (strcmp(argv[argn], "-xt") == 0 ||
  618. strcmp(argv[argn], "--extractt") == 0) {
  619. config_extract = TYPE_TRX;
  620. action_type = config_extract;
  621. }
  622. // doh
  623. else {
  624. printf("%s: Unrecognised command parameter [%s],"
  625. " exiting.\n", vernam, argv[argn]);
  626. usage(1, argv[0]);
  627. }
  628. ++argn;
  629. }
  630. if ( argn != argc )
  631. usage(1, argv[0]);
  632. }
  633.  
  634.  
  635.  
  636.  
  637. // Evil way to make main main
  638. #ifdef WIN32
  639. int _tmain(int argc, _TCHAR* argv[]) {
  640. #else
  641. int main(int argc, char **argv) {
  642. #endif /* win32 */
  643.  
  644. int maxlen;
  645. int bytes;
  646. int totlen;
  647. int trxlen;
  648. int fotlen;
  649. int fromtrx;
  650. int pullen;
  651.  
  652. #if O_BINARY
  653. _setmode (fileno(stdin), O_BINARY);
  654. _setmode (fileno(stdout), O_BINARY);
  655. #endif
  656. /* obtain configuration state */
  657. parse_args(argc, argv);
  658.  
  659. /* input validation check */
  660. if (input_validation() < 0) {
  661. return -1;
  662. }
  663.  
  664. /* create memory region for firmware storage */
  665. if ((header = (struct belky_header *)malloc(config_maxlen)) == NULL) {
  666. printf("%s: unable to malloc [%d] bytes.\n",
  667. vernam, config_maxlen);
  668. if (header)
  669. free(header);
  670. return -1;
  671. }
  672. memset(header, 0, config_maxlen);
  673.  
  674. /* v0.5 supports trx de/construction */
  675. theader = (struct trx_header *)((char *)header +
  676. sizeof(struct belky_header));
  677.  
  678. /* v0.4 supports image extraction */
  679. if (config_extract) {
  680.  
  681. if (action_type == TYPE_TRX) {
  682. maxlen = config_maxlen - sizeof(struct belky_header);
  683. /* read firmware from linux.trx file */
  684. bytes = read_in_data_file(config_trx,
  685. (void *)theader, maxlen, 1);
  686. } else {
  687. maxlen = config_maxlen;
  688. /* read firmware from firmware.belkin file */
  689. bytes = read_in_data_file(config_output,
  690. (void *)header, maxlen, 1);
  691. }
  692. if (bytes < 0) {
  693. return -1;
  694. }
  695.  
  696. /* pull out extended files? */
  697. if (action_type == TYPE_EXTENDED) {
  698.  
  699. /* setup the footer location */
  700. footer = (struct belky_footer *)((char *)header +
  701. (uint32_t)PULL32_LE(theader->len) +
  702. sizeof(struct belky_footer));
  703.  
  704. /* pull out trx ?*/
  705. if (strlen(config_trx) !=0) {
  706. pullen = PULL32_LE(theader->len);
  707. write_firmware(config_trx, (char *)theader,
  708. pullen);
  709. if (bytes < 0) {
  710. return -1;
  711. }
  712. }
  713.  
  714. /* pull out nvram ?*/
  715. if (strlen(config_userconf) !=0) {
  716. pullen = PULL32_LE(footer->len) -
  717. sizeof(struct belky_footer);
  718. write_firmware(config_userconf,
  719. (char *)footer +
  720. sizeof(struct belky_footer),
  721. pullen);
  722. if (bytes < 0) {
  723. return -1;
  724. }
  725. }
  726.  
  727. }
  728.  
  729. /* pull out kernel ?*/
  730. if (strlen(config_kernel) !=0) {
  731. if (theader->offsets[0] == 0) {
  732. printf("%s: no kernel file offset found\n",
  733. vernam);
  734. return -1;
  735. }
  736. if (theader->offsets[1] != 0) {
  737. pullen = PULL32_LE(theader->offsets[1]) -
  738. PULL32_LE(theader->offsets[0]);
  739. } else {
  740. pullen = PULL32_LE(theader->len) -
  741. PULL32_LE(theader->offsets[0]);
  742. }
  743. write_firmware(config_kernel,
  744. (char *)theader + theader->offsets[0],
  745. pullen);
  746. if (bytes < 0) {
  747. return -1;
  748. }
  749. }
  750.  
  751. /* pull out fs0 ?*/
  752. if (strlen(config_fs0) !=0) {
  753. if (theader->offsets[1] == 0) {
  754. printf("%s: no fs0 offset found\n",
  755. vernam);
  756. return -1;
  757. }
  758. if (theader->offsets[2] != 0) {
  759. pullen = PULL32_LE(theader->offsets[2]) -
  760. PULL32_LE(theader->offsets[1]);
  761. } else {
  762. pullen = PULL32_LE(theader->len) -
  763. PULL32_LE(theader->offsets[1]);
  764. }
  765. write_firmware(config_fs0,
  766. (char *)theader + theader->offsets[1],
  767. pullen);
  768. if (bytes < 0) {
  769. return -1;
  770. }
  771. }
  772.  
  773. /* pull out fs1 ?*/
  774. if (strlen(config_fs1) !=0) {
  775. if (theader->offsets[2] == 0) {
  776. printf("%s: no fs1 offset found\n",
  777. vernam);
  778. return -1;
  779. }
  780. pullen = PULL32_LE(theader->len) -
  781. PULL32_LE(theader->offsets[2]);
  782. write_firmware(config_fs1,
  783. (char *)theader + theader->offsets[2],
  784. pullen);
  785. if (bytes < 0) {
  786. return -1;
  787. }
  788. }
  789.  
  790.  
  791. } else {
  792. /* add the meat - build the trx component first */
  793. trxlen = 0;
  794.  
  795. /* assumption based on no defaults .. */
  796. if (strlen(config_kernel) != 0) {
  797.  
  798. /* not created from a trx file */
  799. fromtrx = 0;
  800.  
  801. /* create trx from source files */
  802. trxlen = sizeof(struct trx_header);
  803.  
  804. /* + kernel */
  805. theader->offsets[0] = STORE32_LE(trxlen);
  806. maxlen = config_maxlen - sizeof(struct belky_header) -
  807. trxlen;
  808. if (action_type == TYPE_EXTENDED)
  809. maxlen = maxlen - sizeof(struct belky_footer);
  810. bytes = read_in_data_file(config_kernel,
  811. (void *)theader + trxlen, maxlen, 1);
  812. if (bytes < 0) {
  813. return -1;
  814. }
  815.  
  816. /* structure alignment? take ur word 4 it. */
  817. if (fs_count > 0) {
  818. if (bytes & (4-1)) {
  819. // memset(theader + trxlen + 4, 0,
  820. // 4 - (bytes & (4-1)));
  821. bytes += 4 - (bytes & (4-1));
  822. }
  823. }
  824. trxlen += bytes;
  825.  
  826. if (strlen(config_fs0) != 0) {
  827.  
  828. /* + fs0 */
  829. theader->offsets[1] = STORE32_LE(trxlen);
  830. maxlen = config_maxlen -
  831. sizeof(struct belky_header) -
  832. trxlen;
  833. if (action_type == TYPE_EXTENDED)
  834. maxlen = maxlen -
  835. sizeof(struct belky_footer);
  836. bytes = read_in_data_file(config_fs0,
  837. (void *)theader + trxlen, maxlen, 1);
  838. if (bytes < 0) {
  839. return -1;
  840. }
  841.  
  842. /* structure alignment? take ur word 4 it. */
  843. if (fs_count > 1) {
  844. if (bytes & (4-1)) {
  845. memset(theader + trxlen + 4, 0,
  846. 4 - (bytes & (4-1)));
  847. bytes += 4 - (bytes & (4-1));
  848. }
  849. }
  850. trxlen += bytes;
  851. }
  852.  
  853. if (strlen(config_fs1) != 0) {
  854.  
  855. /* + fs1 */
  856. theader->offsets[2] = STORE32_LE(trxlen);
  857. maxlen = config_maxlen -
  858. sizeof(struct belky_header) -
  859. trxlen;
  860. if (action_type == TYPE_EXTENDED)
  861. maxlen = maxlen -
  862. sizeof(struct belky_footer);
  863. bytes = read_in_data_file(config_fs1,
  864. (void *)theader + trxlen, maxlen, 1);
  865. if (bytes < 0) {
  866. return -1;
  867. }
  868.  
  869. /* structure alignment? take ur word 4 it. */
  870. /*
  871. if (fs_count > 1) {
  872.   if (bytes & (4-1)) {
  873.   memset(theader + trxlen + 4, 0,
  874. 4 - (bytes & (4-1)));
  875. bytes += 4 - (bytes & (4-1));
  876.   }
  877. }
  878. */
  879. trxlen += bytes;
  880. }
  881.  
  882. bytes = trxlen & (0x1000 - 1);
  883. if (bytes) {
  884. // memset(theader + trxlen, 0, 0x1000 - bytes);
  885. trxlen += 0x1000 - bytes;
  886. }
  887.  
  888. } else {
  889.  
  890. /* created from a trx file */
  891. fromtrx = 1;
  892.  
  893. /* read in the linux.trx file */
  894. maxlen = config_maxlen - sizeof(struct belky_header) -
  895. sizeof(struct belky_footer);
  896. bytes = read_in_data_file(config_trx,
  897. (void *)header + sizeof(struct belky_header),
  898. maxlen, 1);
  899. if (bytes < 0) {
  900. return -1;
  901. }
  902. trxlen = bytes;
  903.  
  904. }
  905.  
  906. if (action_type == TYPE_TRX) {
  907.  
  908. /* total length of trx firmware */
  909. totlen = trxlen;
  910.  
  911. } else {
  912.  
  913. /* total length of extended firmware, so far */
  914. totlen = sizeof(struct belky_header) + trxlen;
  915.  
  916. /* set the correct footer offset */
  917. footer = (struct belky_footer *)((char *)header +
  918. (uint32_t)totlen);
  919.  
  920. if (strlen(config_userconf) == 0) {
  921. printf("%s: extended firmware requested, "
  922. "NVRAM file is missing "
  923. "(try --help).\n", vernam);
  924. return -1;
  925. }
  926.  
  927. /* read in the user.conf file */
  928. maxlen = config_maxlen - sizeof(struct belky_footer) -
  929. totlen;
  930. bytes = read_in_data_file(config_userconf,
  931. (void *)footer + sizeof(struct belky_footer),
  932. maxlen, 1);
  933. if (bytes < 0) {
  934. return -1;
  935. }
  936. /* structure alignment? take ur word 4 it. */
  937. /*
  938. if (bytes & (4-1)) {
  939. bytes += 4 - (bytes & (4-1));
  940.   }
  941. */
  942. fotlen = sizeof(struct belky_footer) + bytes;
  943.  
  944. totlen += fotlen;
  945.  
  946. /*
  947. fotlen = sizeof(footer->version) +
  948. sizeof(footer->pad_0) +
  949. sizeof(footer->pad_1) +
  950. sizeof(footer->pad_2) + bytes;
  951. */
  952. }
  953.  
  954. /* time to colour in the picture */
  955. if (fill_headers((uint32_t)totlen, (uint32_t)trxlen,
  956. (uint32_t)fotlen, fromtrx) < 0) {
  957. return -1;
  958. }
  959.  
  960. maxlen = totlen;
  961.  
  962. /* write firmware to firmware.belkin file */
  963. if (action_type == TYPE_TRX) {
  964. bytes = write_firmware(config_trx, (char *)theader,
  965. maxlen);
  966. } else {
  967. bytes = write_firmware(config_output, (char *)header,
  968. maxlen);
  969. }
  970. if (bytes < 0) {
  971. return -1;
  972. }
  973.  
  974. }
  975.  
  976. return(0);
  977. }
  978.  
  979.  
  980. /**********************************************************************/
  981. /* The following was grabbed and tweaked from the old snippets collection
  982.  * of public domain C code. */
  983. /**********************************************************************\
  984. |* Demonstration program to compute the 32-bit CRC used as the frame *|
  985. |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
  986. |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
  987. |* protocol). The 32-bit FCS was added via the Federal Register, *|
  988. |* 1 June 1982, p.23798. I presume but don't know for certain that *|
  989. |* this polynomial is or will be included in CCITT V.41, which *|
  990. |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
  991. |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
  992. |* errors by a factor of 10^-5 over 16-bit FCS. *|
  993. \**********************************************************************/
  994.  
  995. /* Copyright (C) 1986 Gary S. Brown. You may use this program, or
  996.   code or tables extracted from it, as desired without restriction. */
  997.  
  998. /* First, the polynomial itself and its table of feedback terms. The */
  999. /* polynomial is */
  1000. /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
  1001. /* Note that we take it "backwards" and put the highest-order term in */
  1002. /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
  1003. /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
  1004. /* the MSB being 1. */
  1005.  
  1006. /* Note that the usual hardware shift register implementation, which */
  1007. /* is what we're using (we're merely optimizing it by doing eight-bit */
  1008. /* chunks at a time) shifts bits into the lowest-order term. In our */
  1009. /* implementation, that means shifting towards the right. Why do we */
  1010. /* do it this way? Because the calculated CRC must be transmitted in */
  1011. /* order from highest-order term to lowest-order term. UARTs transmit */
  1012. /* characters in order from LSB to MSB. By storing the CRC this way, */
  1013. /* we hand it to the UART in the order low-byte to high-byte; the UART */
  1014. /* sends each low-bit to hight-bit; and the result is transmission bit */
  1015. /* by bit from highest- to lowest-order term without requiring any bit */
  1016. /* shuffling on our part. Reception works similarly. */
  1017.  
  1018. /* The feedback terms table consists of 256, 32-bit entries. Notes: */
  1019. /* */
  1020. /* 1. The table can be generated at runtime if desired; code to do so */
  1021. /* is shown later. It might not be obvious, but the feedback */
  1022. /* terms simply represent the results of eight shift/xor opera- */
  1023. /* tions for all combinations of data and CRC register values. */
  1024. /* */
  1025. /* 2. The CRC accumulation logic is the same for all CRC polynomials, */
  1026. /* be they sixteen or thirty-two bits wide. You simply choose the */
  1027. /* appropriate table. Alternatively, because the table can be */
  1028. /* generated at runtime, you can start by generating the table for */
  1029. /* the polynomial in question and use exactly the same "updcrc", */
  1030. /* if your application needn't simultaneously handle two CRC */
  1031. /* polynomials. (Note, however, that XMODEM is strange.) */
  1032. /* */
  1033. /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
  1034. /* of course, 32-bit entries work OK if the high 16 bits are zero. */
  1035. /* */
  1036. /* 4. The values must be right-shifted by eight bits by the "updcrc" */
  1037. /* logic; the shift must be unsigned (bring in zeroes). On some */
  1038. /* hardware you could probably optimize the shift in assembler by */
  1039. /* using byte-swap instructions. */
  1040.  
  1041. static const uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
  1042. 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
  1043. 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
  1044. 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
  1045. 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
  1046. 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
  1047. 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
  1048. 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
  1049. 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
  1050. 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
  1051. 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
  1052. 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
  1053. 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
  1054. 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
  1055. 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
  1056. 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
  1057. 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
  1058. 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
  1059. 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
  1060. 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
  1061. 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
  1062. 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
  1063. 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
  1064. 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
  1065. 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
  1066. 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
  1067. 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
  1068. 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
  1069. 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
  1070. 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
  1071. 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
  1072. 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
  1073. 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
  1074. 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
  1075. 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
  1076. 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
  1077. 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
  1078. 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
  1079. 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
  1080. 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
  1081. 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
  1082. 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
  1083. 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
  1084. 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
  1085. };
  1086.  
  1087. #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
  1088.  
  1089. uint32_t crc32buf(char *buf, size_t len)
  1090. {
  1091. uint32_t crc;
  1092. crc = 0xFFFFFFFF;
  1093. for ( ; len; --len, ++buf)
  1094. {
  1095. crc = UPDC32(*buf, crc);
  1096. }
  1097. return crc;
  1098. }
kordewiner