+++ /dev/null
-/*
- Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- L. Peter Deutsch
- ghost@aladdin.com
-
- */
-/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
-/*
- Independent implementation of MD5 (RFC 1321).
-
- This code implements the MD5 Algorithm defined in RFC 1321, whose
- text is available at
- http://www.ietf.org/rfc/rfc1321.txt
- The code is derived from the text of the RFC, including the test suite
- (section A.5) but excluding the rest of Appendix A. It does not include
- any code or documentation that is identified in the RFC as being
- copyrighted.
-
- The original and principal author of md5.c is L. Peter Deutsch
- <ghost@aladdin.com>. Other authors are noted in the change history
- that follows (in reverse chronological order):
-
- 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
- either statically or dynamically; added missing #include <string.h>
- in library.
- 2002-03-11 lpd Corrected argument list for main(), and added int return
- type, in test program and T value program.
- 2002-02-21 lpd Added missing #include <stdio.h> in test program.
- 2000-07-03 lpd Patched to eliminate warnings about "constant is
- unsigned in ANSI C, signed in traditional"; made test program
- self-checking.
- 1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
- 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
- 1999-05-03 lpd Original version.
- */
-
-#include "md5.h"
-#include <string.h>
-
-#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
-#ifdef ARCH_IS_BIG_ENDIAN
-# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
-#else
-# define BYTE_ORDER 0
-#endif
-
-#define T_MASK ((md5_word_t)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3 0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6 0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9 0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13 0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16 0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19 0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22 0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25 0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28 0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31 0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35 0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38 0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41 0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44 0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47 0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50 0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53 0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57 0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60 0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63 0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
- md5_word_t
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
- md5_word_t t;
-#if BYTE_ORDER > 0
- /* Define storage only for big-endian CPUs. */
- md5_word_t X[16];
-#else
- /* Define storage for little-endian or both types of CPUs. */
- md5_word_t xbuf[16];
- const md5_word_t *X;
-#endif
-
- {
-#if BYTE_ORDER == 0
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
-#endif
-#if BYTE_ORDER <= 0 /* little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if (!((data - (const md5_byte_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const md5_word_t *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
-#endif
-#if BYTE_ORDER == 0
- else /* dynamic big-endian */
-#endif
-#if BYTE_ORDER >= 0 /* big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const md5_byte_t *xp = data;
- int i;
-
-# if BYTE_ORDER == 0
- X = xbuf; /* (dynamic only) */
-# else
-# define xbuf X /* (static only) */
-# endif
- for (i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
-#endif
- }
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + F(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 7, T1);
- SET(d, a, b, c, 1, 12, T2);
- SET(c, d, a, b, 2, 17, T3);
- SET(b, c, d, a, 3, 22, T4);
- SET(a, b, c, d, 4, 7, T5);
- SET(d, a, b, c, 5, 12, T6);
- SET(c, d, a, b, 6, 17, T7);
- SET(b, c, d, a, 7, 22, T8);
- SET(a, b, c, d, 8, 7, T9);
- SET(d, a, b, c, 9, 12, T10);
- SET(c, d, a, b, 10, 17, T11);
- SET(b, c, d, a, 11, 22, T12);
- SET(a, b, c, d, 12, 7, T13);
- SET(d, a, b, c, 13, 12, T14);
- SET(c, d, a, b, 14, 17, T15);
- SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + G(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 1, 5, T17);
- SET(d, a, b, c, 6, 9, T18);
- SET(c, d, a, b, 11, 14, T19);
- SET(b, c, d, a, 0, 20, T20);
- SET(a, b, c, d, 5, 5, T21);
- SET(d, a, b, c, 10, 9, T22);
- SET(c, d, a, b, 15, 14, T23);
- SET(b, c, d, a, 4, 20, T24);
- SET(a, b, c, d, 9, 5, T25);
- SET(d, a, b, c, 14, 9, T26);
- SET(c, d, a, b, 3, 14, T27);
- SET(b, c, d, a, 8, 20, T28);
- SET(a, b, c, d, 13, 5, T29);
- SET(d, a, b, c, 2, 9, T30);
- SET(c, d, a, b, 7, 14, T31);
- SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + H(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 5, 4, T33);
- SET(d, a, b, c, 8, 11, T34);
- SET(c, d, a, b, 11, 16, T35);
- SET(b, c, d, a, 14, 23, T36);
- SET(a, b, c, d, 1, 4, T37);
- SET(d, a, b, c, 4, 11, T38);
- SET(c, d, a, b, 7, 16, T39);
- SET(b, c, d, a, 10, 23, T40);
- SET(a, b, c, d, 13, 4, T41);
- SET(d, a, b, c, 0, 11, T42);
- SET(c, d, a, b, 3, 16, T43);
- SET(b, c, d, a, 6, 23, T44);
- SET(a, b, c, d, 9, 4, T45);
- SET(d, a, b, c, 12, 11, T46);
- SET(c, d, a, b, 15, 16, T47);
- SET(b, c, d, a, 2, 23, T48);
-#undef SET
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
- t = a + I(b,c,d) + X[k] + Ti;\
- a = ROTATE_LEFT(t, s) + b
- /* Do the following 16 operations. */
- SET(a, b, c, d, 0, 6, T49);
- SET(d, a, b, c, 7, 10, T50);
- SET(c, d, a, b, 14, 15, T51);
- SET(b, c, d, a, 5, 21, T52);
- SET(a, b, c, d, 12, 6, T53);
- SET(d, a, b, c, 3, 10, T54);
- SET(c, d, a, b, 10, 15, T55);
- SET(b, c, d, a, 1, 21, T56);
- SET(a, b, c, d, 8, 6, T57);
- SET(d, a, b, c, 15, 10, T58);
- SET(c, d, a, b, 6, 15, T59);
- SET(b, c, d, a, 13, 21, T60);
- SET(a, b, c, d, 4, 6, T61);
- SET(d, a, b, c, 11, 10, T62);
- SET(c, d, a, b, 2, 15, T63);
- SET(b, c, d, a, 9, 21, T64);
-#undef SET
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- pms->abcd[0] += a;
- pms->abcd[1] += b;
- pms->abcd[2] += c;
- pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
- pms->count[0] = pms->count[1] = 0;
- pms->abcd[0] = 0x67452301;
- pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
- pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
- pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
- const md5_byte_t *p = data;
- int left = nbytes;
- int offset = (pms->count[0] >> 3) & 63;
- md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
- if (nbytes <= 0)
- return;
-
- /* Update the message length. */
- pms->count[1] += nbytes >> 29;
- pms->count[0] += nbits;
- if (pms->count[0] < nbits)
- pms->count[1]++;
-
- /* Process an initial partial block. */
- if (offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
- }
-
- /* Process full blocks. */
- for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
-
- /* Process a final partial block. */
- if (left)
- memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
- static const md5_byte_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
- md5_byte_t data[8];
- int i;
-
- /* Save the length before padding. */
- for (i = 0; i < 8; ++i)
- data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
- /* Pad to 56 bytes mod 64. */
- md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
- /* Append the length. */
- md5_append(pms, data, 8);
- for (i = 0; i < 16; ++i)
- digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
+++ /dev/null
-/*
-
- WRT350Nv2-Builder 2.4 (previously called buildimg)
- Copyright (C) 2008-2009 Dirk Teurlings <info@upexia.nl>
- Copyright (C) 2009-2011 Matthias Buecher (http://www.maddes.net/)
-
- This program 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 2 of the License, or
- (at your option) any later version.
-
- This program 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 this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- A lot of thanks to Kaloz and juhosg from OpenWRT and Lennert Buytenhek from
- marvell for helping me figure this one out. This code is based on bash
- scripts wrote by Peter van Valderen so the real credit should go to him.
-
- This program reads the provided parameter file and creates an image which can
- be used to flash a Linksys WRT350N v2 from stock firmware.
- The trick is to fill unused space in the bin file with random, so that the
- resulting zip file passes the size check of the stock firmware.
-
- The parameter file layout for an original Linksys firmware:
- :kernel 0x001A0000 /path/to/uImage
- :rootfs 0 /path/to/root.squashfs
- :u-boot 0 /path/to/u-boot.bin
- #version 0x2020
-
- Additionally since v2.4 an already complete image can be used:
- :image 0 /path/to/librecmc-wrt350nv2-[squashfs|jffs2-64k].img
-
- args:
- 1 wrt350nv2.par parameter file describing the image layout
- 2 wrt350nv2.img output file for linksys style image
-
- A u-boot image inside the bin file is not necessary.
- The version is not important.
- The name of the bin file is not important, but still "wrt350n.bin" is used to
- keep as close as possible to the stock firmware.
-
- Linksys assumes that no mtd will be used to its maximum, so the last 16 bytes
- of the mtd are abused to define the length of the next mtd content (4 bytes for
- size + 12 pad bytes).
-
- At the end of "rootfs" additional 16 bytes are abused for some data and a
- highly important eRcOmM identifier, so the last 32 bytes of "rootfs" are abused.
-
- At the end of "u-boot" 128 bytes are abused for some data, a checksum and a
- highly important sErCoMm identifier.
-
-
- This program uses a special GNU scanf modifier to allocate
- sufficient memory for a strings with unknown length.
- See http://www.kernel.org/doc/man-pages/online/pages/man3/scanf.3.html#NOTES
-
-
- To extract everything from a Linksys style firmware image see
- https://forum.openwrt.org/viewtopic.php?pid=92928#p92928
-
- Changelog:
- v2.4 - added ":image" definition for parameter file, this allows
- to use a complete sysupgrade image without any kernel size check
- v2.3 - allow jffs by adding its magic number (0x8519)
- added parameter option -i to ignore unknown magic numbers
- v2.2 - fixed checksum byte calculation for other versions than 0x2019
- fixed rare problem with padsize
- updated info to stock firmware 2.00.20
- fixed typos
- v2.1 - used "wrt350n.bin" for the created image (closer to stock)
- added option to create the image in two separate steps (-b / -z)
- v2.0 - complete re-write
-
-*/
-
-// includes
-#define _GNU_SOURCE // for GNU's basename()
-#include <assert.h>
-#include <errno.h> // errno
-#include <stdarg.h>
-#include <stdio.h> // fopen(), fread(), fclose(), etc.
-#include <stdlib.h> // system(), etc.
-#include <string.h> // basename(), strerror(), strdup(), etc.
-#include <unistd.h> // optopt(), access(), etc.
-#include <libgen.h>
-#include <sys/wait.h> // WEXITSTATUS, etc.
-
-// custom includes
-#include "md5.h" // MD5 routines
-#include "upgrade.h" // Linksys definitions from firmware 2.0.19 (unchanged up to 2.0.20)
-
-
-// version info
-#define VERSION "2.4"
-char program_info[] = "WRT350Nv2-Builder v%s by Dirk Teurlings <info@upexia.nl> and Matthias Buecher (http://www.maddes.net/)\n";
-
-// verbosity
-#define DEBUG 1
-#define DEBUG_LVL2 2
-int verbosity = 0;
-
-// mtd info
-typedef struct {
- char *name;
- int offset;
- int size;
- char *filename;
- long int filesize;
- unsigned char magic[2];
-} mtd_info;
-
-mtd_info mtd_kernel = { "kernel", 0, 0, NULL, 0L, { 0, 0 } };
-mtd_info mtd_rootfs = { "rootfs", 0, 0, NULL, 0L, { 0, 0 } };
-mtd_info mtd_image = { "image", 0, 0, NULL, 0L, { 0, 0 } };
-mtd_info mtd_uboot = { "u-boot", 0, 0, NULL, 0L, { 0, 0 } };
-
-#define ROOTFS_END_OFFSET 0x00760000
-#define ROOTFS_MIN_OFFSET 0x00640000 // should be filled up to here, to make sure that the zip file is big enough to pass the size check of the stock firmware
- // 2.0.17: filled up to 0x00640000
- // 2.0.19: filled up to 0x00670000
- // 2.0.20: filled up to 0x00670000
-
-// rootfs statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0x0075FFE0 -n 16 "wrt350n.bin" ; echo -en "\n"
-unsigned char product_id[] = { 0x00, 0x03 }; // seems to be a fixed value
-unsigned char protocol_id[] = { 0x00, 0x00 }; // seems to be a fixed value
-unsigned char fw_version[] = { 0x20, 0x20 };
-unsigned char rootfs_unknown[] = { 0x90, 0xF7 }; // seems to be a fixed value
-unsigned char sign[] = { 0x65, 0x52, 0x63, 0x4F, 0x6D, 0x4D, 0x00, 0x00 }; // eRcOmM
-
-// u-boot statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0x007FFF80 -n 128 "wrt350n.bin" ; echo -en "\n"
-//unsigned char sn[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // (12) seems to be an unused value
-//unsigned char pin[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // (8) seems to be an unused value
-//unsigned char node[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // (25) seems to be an unused value
-// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-//unsigned char checksum[] = { 0xE9 }; // (1) is calculated, does it belong to node?
-unsigned char pid[] = { 0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D, 0x00, 0x01, 0x00, 0x00, 0x59, 0x42, 0x50, 0x00, 0x01, // (70) seems to be a fixed value, except for fw version
- 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, // protocol id?
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // protocol id?
- 0x12, 0x34, // firmware version, same as in rootfs
- 0x00, 0x00, 0x00, 0x04,
- 0x73, 0x45, 0x72, 0x43, 0x6F, 0x4D, 0x6D }; // sErCoMm
-
-// img statics via: hexdump -v -e '1/1 "0x%02X, "' -s 0 -n 512 "WRT350N-EU-ETSI-2.00.19.img" ; echo -en "\n" (unchanged up to 2.0.20)
-unsigned char img_hdr[] = { 0x00, 0x01, 0x00, 0x00, 0x59, 0x42, 0x50, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x00, 0x00,
- 0x12, 0x34, // firmware version, same as in rootfs
- 0x00, 0x00, 0x00, 0x04, 0x61, 0x44, 0x6D, 0x42, 0x6C, 0x4B, 0x3D, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, // md5 checksum
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-unsigned char img_eof[] = { 0xFF };
-
-
-void lprintf(int outputlevel, char *fmt, ...) {
- va_list argp;
- if (outputlevel <= verbosity) {
- va_start(argp, fmt);
- vprintf(fmt, argp);
- va_end(argp);
- }
-}
-
-
-int parse_par_file(FILE *f_par) {
- int exitcode = 0;
-
- char *buffer;
- size_t buffer_size;
- char *line;
-
- int lineno;
- int count;
-
- char string1[256];
- char string2[256];
- int value;
-
- mtd_info *mtd;
- FILE *f_in;
- int f_exitcode = 0;
-
- // read all lines
- buffer_size = 1000;
- buffer = NULL;
- lineno = 0;
- while (!feof(f_par)) {
- // read next line into memory
- do {
- // allocate memory for input line
- if (!buffer) {
- buffer = malloc(buffer_size);
- }
- if (!buffer) {
- exitcode = 1;
- printf("parse_par_file: can not allocate %i bytes\n", (int) buffer_size);
- break;
- }
-
- line = fgets(buffer, buffer_size, f_par);
- if (!line) {
- exitcode = ferror(f_par);
- if (exitcode) {
- printf("parse_par_file: %s\n", strerror(exitcode));
- }
- break;
- }
-
- // if buffer was not completely filled, then assume that line is complete
- count = strlen(buffer) + 1;
- if (count-- < buffer_size) {
- break;
- }
-
- // otherwise....
-
- // reset file position to line start
- value = fseek(f_par, -count, SEEK_CUR);
- if (value == -1) {
- exitcode = errno;
- printf("parse_par_file: %s\n", strerror(exitcode));
- break;
- }
-
- // double buffer size
- free(buffer);
- buffer = NULL;
- buffer_size *= 2;
- lprintf(DEBUG_LVL2, " extending buffer to %i bytes\n", buffer_size);
- } while (1);
- if ((!line) || (exitcode)) {
- break;
- }
-
- lineno++; // increase line number
-
- lprintf(DEBUG_LVL2, " line %i (%i) %s", lineno, count, line);
-
- value = 0;
- mtd = NULL;
-
- // split line if starting with a colon
- switch (line[0]) {
- case ':':
- count = sscanf(line, ":%255s %i %255s", string1, &value, string2);
- if (count != 3) {
- printf("line %i does not meet defined format (:<mtdname> <mtdsize> <file>)\n", lineno);
- } else {
- // populate mtd_info if supported mtd names
- if (!strcmp(string1, mtd_kernel.name)) {
- mtd = &mtd_kernel;
- } else if (!strcmp(string1, mtd_rootfs.name)) {
- mtd = &mtd_rootfs;
- } else if (!strcmp(string1, mtd_uboot.name)) {
- mtd = &mtd_uboot;
- } else if (!strcmp(string1, mtd_image.name)) {
- mtd = &mtd_image;
- }
-
- if (!mtd) {
- printf("unknown mtd %s in line %i\n", string1, lineno);
- } else if (mtd->filename) {
- f_exitcode = 1;
- printf("mtd %s in line %i multiple definitions\n", string1, lineno);
- } else {
- mtd->size = value;
- mtd->filename = strdup(string2);
-
- // Get file size
- f_in = fopen(mtd->filename, "rb");
- if (!f_in) {
- f_exitcode = errno;
- printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
- } else {
- value = fread(&mtd->magic, 1, 2, f_in);
- if (value < 2) {
- if (ferror(f_in)) {
- f_exitcode = ferror(f_in);
- printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
- } else {
- f_exitcode = 1;
- printf("input file %s: smaller than two bytes, no magic code\n", mtd->filename);
- }
- }
-
- value = fseek(f_in, 0, SEEK_END);
- if (value == -1) {
- f_exitcode = errno;
- printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
- } else {
- mtd->filesize = ftell(f_in);
- if (mtd->filesize == -1) {
- f_exitcode = errno;
- printf("input file %s: %s\n", mtd->filename, strerror(f_exitcode));
- }
- }
-
- fclose(f_in);
- }
-
- lprintf(DEBUG, "mtd %s in line %i: size=0x%08X, filesize=0x%08lX, magic=0x%02X%02X, file=%s\n", mtd->name, lineno, mtd->size, mtd->filesize, mtd->magic[0], mtd->magic[1], mtd->filename);
- }
- }
- break;
- case '#': // integer values
- count = sscanf(line, "#%255s %i", string1, &value);
- if (count != 2) {
- printf("line %i does not meet defined format (#<variable name> <integer>\n", lineno);
- } else {
- if (!strcmp(string1, "version")) {
- // changing version
- fw_version[0] = 0x000000FF & ( value >> 8 );
- fw_version[1] = 0x000000FF & value;
- } else {
- printf("unknown integer variable %s in line %i\n", string1, lineno);
- }
-
- lprintf(DEBUG, "integer variable %s in line %i: 0x%08X\n", string1, lineno, value);
- }
- break;
- case '$': // strings
- count = sscanf(line, "$%255s %255s", string1, string2);
- if (count != 2) {
- printf("line %i does not meet defined format (:<mtdname> <mtdsize> <file>)\n", lineno);
- } else {
-/*
- if (!strcmp(string1, "something")) {
- something = strdup(string2);
- } else {
-*/
- printf("unknown string variable %s in line %i\n", string1, lineno);
-// }
- lprintf(DEBUG, "string variable %s in line %i: %s\n", string1, lineno, string2);
- }
- break;
- default:
- break;
- }
- }
- free(buffer);
-
- if (!exitcode) {
- exitcode = f_exitcode;
- }
-
- return exitcode;
-}
-
-
-int create_bin_file(char *bin_filename) {
- int exitcode = 0;
-
- unsigned char *buffer;
-
- int i;
- mtd_info *mtd;
- int addsize;
- int padsize;
-
- char *rand_filename = "/dev/urandom";
- FILE *f_in;
- int size;
-
- unsigned long int csum;
- unsigned char checksum;
-
- FILE *f_out;
-
- // allocate memory for bin file
- buffer = malloc(KERNEL_CODE_OFFSET + FLASH_SIZE);
- if (!buffer) {
- exitcode = 1;
- printf("create_bin_file: can not allocate %i bytes\n", FLASH_SIZE);
- } else {
- // initialize with zero
- memset(buffer, 0, KERNEL_CODE_OFFSET + FLASH_SIZE);
- }
-
- // add files
- if (!exitcode) {
- for (i = 1; i <= 4; i++) {
- addsize = 0;
- padsize = 0;
-
- switch (i) {
- case 1:
- mtd = &mtd_image;
- padsize = ROOTFS_MIN_OFFSET - mtd->filesize;
- break;
- case 2:
- mtd = &mtd_kernel;
- break;
- case 3:
- mtd = &mtd_rootfs;
- addsize = mtd->filesize;
- padsize = ROOTFS_MIN_OFFSET - mtd_kernel.size - mtd->filesize;
- break;
- case 4:
- mtd = &mtd_uboot;
- addsize = mtd->filesize;
- break;
- default:
- mtd = NULL;
- exitcode = 1;
- printf("create_bin_file: unknown mtd %i\n", i);
- break;
- }
- if (!mtd) {
- break;
- }
- if (!mtd->filename) {
- continue;
- }
-
- lprintf(DEBUG, "adding mtd %s file %s\n", mtd->name, mtd->filename);
-
- // adding file size
- if (addsize) {
- buffer[KERNEL_CODE_OFFSET + mtd->offset - 16] = 0x000000FFL & ( addsize >> 24 );
- buffer[KERNEL_CODE_OFFSET + mtd->offset - 15] = 0x000000FFL & ( addsize >> 16 );
- buffer[KERNEL_CODE_OFFSET + mtd->offset - 14] = 0x000000FFL & ( addsize >> 8 );
- buffer[KERNEL_CODE_OFFSET + mtd->offset - 13] = 0x000000FFL & addsize;
- }
-
- // adding file content
- f_in = fopen(mtd->filename, "rb");
- if (!f_in) {
- exitcode = errno;
- printf("input file %s: %s\n", mtd->filename, strerror(exitcode));
- } else {
- size = fread(&buffer[KERNEL_CODE_OFFSET + mtd->offset], mtd->filesize, 1, f_in);
- if (size < 1) {
- if (ferror(f_in)) {
- exitcode = ferror(f_in);
- printf("input file %s: %s\n", mtd->filename, strerror(exitcode));
- } else {
- exitcode = 1;
- printf("input file %s: smaller than before *doh*\n", mtd->filename);
- }
- }
- fclose(f_in);
- }
-
- // padding
- if (padsize > 0) {
- addsize = padsize & 0x0000FFFF; // start on next 64KB border
- padsize -= addsize;
- }
- if (padsize > 0) {
- printf("mtd %s input file %s is too small (0x%08lX), adding 0x%08X random bytes\n", mtd->name, mtd->filename, mtd->filesize, padsize);
-
- addsize += KERNEL_CODE_OFFSET + mtd->offset + mtd->filesize; // get offset
- lprintf(DEBUG, " padding offset 0x%08X length 0x%08X\n", addsize, padsize);
-
- f_in = fopen(rand_filename, "rb");
- if (!f_in) {
- exitcode = errno;
- printf("input file %s: %s\n", rand_filename, strerror(exitcode));
- } else {
- size = fread(&buffer[addsize], padsize, 1, f_in);
- if (size < 1) {
- if (ferror(f_in)) {
- exitcode = ferror(f_in);
- printf("input file %s: %s\n", rand_filename, strerror(exitcode));
- } else {
- exitcode = 1;
- printf("input file %s: smaller than before *doh*\n", rand_filename);
- }
- }
- }
- fclose(f_in);
- }
- }
- }
-
- // add special contents
- if (!exitcode) {
- lprintf(DEBUG, "adding rootfs special data\n");
- memcpy(&buffer[KERNEL_CODE_OFFSET + PRODUCT_ID_OFFSET], product_id, 2);
- memcpy(&buffer[KERNEL_CODE_OFFSET + PROTOCOL_ID_OFFSET], protocol_id, 2);
- memcpy(&buffer[KERNEL_CODE_OFFSET + FW_VERSION_OFFSET], fw_version, 2);
- memcpy(&buffer[KERNEL_CODE_OFFSET + FW_VERSION_OFFSET + 2], rootfs_unknown, 2);
- memcpy(&buffer[KERNEL_CODE_OFFSET + SIGN_OFFSET], sign, 8); // eRcOmM
-
- lprintf(DEBUG, "adding u-boot special data\n");
-// memcpy(&buffer[KERNEL_CODE_OFFSET + SN_OFF], sn, 12); // ToDo: currently zero, find out what's this for?
-// memcpy(&buffer[KERNEL_CODE_OFFSET + PIN_OFF], pin, 8); // ToDo: currently zero, find out what's this for?
-// memcpy(&buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF], node, 25); // ToDo: currently zero, find out what's this for?
- memcpy(&buffer[KERNEL_CODE_OFFSET + BOOT_ADDR_BASE_OFF + PID_OFFSET], pid, 70); // sErCoMm
- memcpy(&buffer[KERNEL_CODE_OFFSET + BOOT_ADDR_BASE_OFF + PID_OFFSET + 57], fw_version, 2);
-
- lprintf(DEBUG, "adding checksum byte\n");
- csum = 0;
- for (i = 0; i < KERNEL_CODE_OFFSET + FLASH_SIZE; i++) {
- csum += buffer[i];
- }
- lprintf(DEBUG_LVL2, " checksum 0x%016lX (%li)\n", csum, csum);
-
- buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF + 25] = ~csum + 1;
- lprintf(DEBUG, " byte 0x%02X\n", buffer[KERNEL_CODE_OFFSET + NODE_BASE_OFF + 25]);
- }
-
- // write bin file
- if (!exitcode) {
- lprintf(DEBUG, "writing file %s\n", bin_filename);
- f_out = fopen(bin_filename, "wb");
- if (!f_out) {
- exitcode = errno;
- printf("output file %s: %s\n", bin_filename, strerror(exitcode));
- } else {
- size = fwrite(buffer, KERNEL_CODE_OFFSET + FLASH_SIZE, 1, f_out);
- if (size < 1) {
- if (ferror(f_out)) {
- exitcode = ferror(f_out);
- printf("output file %s: %s\n", bin_filename, strerror(exitcode));
- } else {
- exitcode = 1;
- printf("output file %s: unspecified write error\n", bin_filename);
- }
- }
- fclose(f_out);
- }
- }
-
- return exitcode;
-}
-
-
-int create_zip_file(char *zip_filename, char *bin_filename) {
- int exitcode = 0;
-
- char *buffer;
- size_t buffer_size;
- int count;
-
- buffer_size = 1000;
- buffer = NULL;
- do {
- // allocate memory for command line
- if (!buffer) {
- buffer = malloc(buffer_size);
- }
- if (!buffer) {
- exitcode = 1;
- printf("create_zip_file: can not allocate %i bytes\n", (int) buffer_size);
- break;
- }
-
- // if buffer was not completely filled, then line fit in completely
- count = snprintf(buffer, buffer_size, "zip \"%s\" \"%s\"", zip_filename, bin_filename);
- if ((count > -1) && (count < buffer_size)) {
- break;
- }
-
- // otherwise try again with more space
- if (count > -1) { // glibc 2.1
- buffer_size = count + 1; // precisely what is needed
- } else { // glibc 2.0
- buffer_size *= 2; // twice the old size
- }
- free(buffer);
- buffer = NULL;
- lprintf(DEBUG_LVL2, " extending buffer to %i bytes\n", buffer_size);
- } while (1);
-
- if (!exitcode) {
- // zipping binfile
- lprintf(DEBUG, "%s\n", buffer);
- count = system(buffer);
- if ((count < 0) || (WEXITSTATUS(count))) {
- exitcode = 1;
- printf("create_zip_file: can not execute %s bytes\n", buffer);
- }
- }
-
- return exitcode;
-}
-
-
-int create_img_file(FILE *f_out, char *out_filename, char *zip_filename) {
- int exitcode = 0;
-
- md5_state_t state;
- md5_byte_t digest[16];
-
- int i;
- int size;
-
- FILE *f_in;
- unsigned char buffer[1];
-
- // copy firmware version
- memcpy(&img_hdr[50], fw_version, 2);
-
- // clear md5 checksum
- memset(&img_hdr[480], 0, 16);
-
- // prepare md5 checksum calculation
- md5_init(&state);
-
- // add img header
- lprintf(DEBUG_LVL2, " adding img header\n");
- for (i = 0; i < 512; i++) {
- size = fputc(img_hdr[i], f_out);
- if (size == EOF) {
- exitcode = ferror(f_out);
- printf("output file %s: %s\n", out_filename, strerror(exitcode));
- break;
- }
- md5_append(&state, (const md5_byte_t *)&img_hdr[i], 1);
- }
-
- // adding zip file
- if (!exitcode) {
- lprintf(DEBUG_LVL2, " adding zip file\n");
- f_in = fopen(zip_filename, "rb");
- if (!f_in) {
- exitcode = errno;
- printf("input file %s: %s\n", zip_filename, strerror(exitcode));
- } else {
- while ((size = fgetc(f_in)) != EOF) {
- buffer[0] = size;
-
- size = fputc(buffer[0], f_out);
- if (size == EOF) {
- exitcode = ferror(f_out);
- printf("output file %s: %s\n", out_filename, strerror(exitcode));
- break;
- }
- md5_append(&state, (const md5_byte_t *)buffer, 1);
- }
- if (ferror(f_in)) {
- exitcode = ferror(f_in);
- printf("input file %s: %s\n", zip_filename, strerror(exitcode));
- }
- }
-
- }
-
- // add end byte
- if (!exitcode) {
- lprintf(DEBUG_LVL2, " adding img eof byte\n");
- size = fputc(img_eof[0], f_out);
- if (size == EOF) {
- exitcode = ferror(f_out);
- printf("output file %s: %s\n", out_filename, strerror(exitcode));
- }
- md5_append(&state, (const md5_byte_t *)img_eof, 1);
- }
-
- // append salt to md5 checksum
- md5_append(&state, (const md5_byte_t *)"A^gU*<>?RFY@#DR&Z", 17);
-
- // finish md5 checksum calculation
- md5_finish(&state, digest);
-
- // write md5 checksum into img header
- if (!exitcode) {
- lprintf(DEBUG_LVL2, " writing md5 checksum into img header of file\n");
-
- size = fseek(f_out, 480, SEEK_SET);
- if (size == -1) {
- exitcode = errno;
- printf("output file %s: %s\n", out_filename, strerror(exitcode));
- } else {
- size = fwrite(digest, 16, 1, f_out);
- if (size < 1) {
- if (ferror(f_out)) {
- exitcode = ferror(f_out);
- printf("output file %s: %s\n", out_filename, strerror(exitcode));
- } else {
- exitcode = 1;
- printf("output file %s: unspecified write error\n", out_filename);
- }
- }
- }
-
- fclose(f_in);
- }
-
- return exitcode;
-}
-
-
-int main(int argc, char *argv[]) {
- int exitcode = 0;
-
- int help;
- int onlybin;
- int havezip;
- int ignoremagic;
- char option;
- char *par_filename = NULL;
- char *img_filename = NULL;
- char *base_filename = NULL;
- char *bin_filename = NULL;
- char *zip_filename = NULL;
-
- FILE *f_par = NULL;
- FILE *f_img = NULL;
-
- int i;
- mtd_info *mtd;
- int noupdate;
- int sizecheck;
- int magiccheck;
- int magicerror;
-
-
-// display program header
- printf(program_info, VERSION);
-
-
-// command line processing
- // options
- help = 0;
- onlybin = 0;
- havezip = 0;
- ignoremagic = 0;
- while ((option = getopt(argc, argv, "hbzif:v")) != -1) {
- switch(option) {
- case 'h':
- help = 1;
- break;
- case 'b':
- onlybin = 1;
- break;
- case 'z':
- havezip = 1;
- break;
- case 'i':
- ignoremagic = 1;
- break;
- case 'f':
- sizecheck = sscanf(optarg, "%i", &i);
- if (sizecheck != 1) {
- printf("Firmware version of -f option not a valid integer\n");
- exitcode = 1;
- } else {
- fw_version[0] = 0x000000FF & ( i >> 8 );
- fw_version[1] = 0x000000FF & i;
- }
- break;
- case 'v':
- verbosity++;
- break;
- case ':': // option with missing operand
- printf("Option -%c requires an operand\n", optopt);
- exitcode = 1;
- break;
- case '?':
- printf("Unrecognized option: -%c\n", optopt);
- exitcode = 1;
- break;
- }
- }
-
- // files
- for ( ; optind < argc; optind++) {
- if (!par_filename) {
- par_filename = argv[optind];
-
- if (access(par_filename, R_OK)) {
- if (havezip) {
- printf("No read access to zip file %s\n", par_filename);
- } else {
- printf("No read access to parameter or zip file %s\n", par_filename);
- }
- exitcode = 1;
- }
-
- continue;
- }
-
- if ((!onlybin) && (!img_filename)) {
- img_filename = argv[optind];
-
- if (!access(img_filename, F_OK)) { // if file already exists then check write access
- if (access(img_filename, W_OK)) {
- printf("No write access to image file %s\n", img_filename);
- exitcode = 1;
- }
- }
-
- continue;
- }
-
- printf("Too many files stated\n");
- exitcode = 1;
- break;
- }
-
- // file name checks
- if (!par_filename) {
- if (havezip) {
- printf("Zip file not stated\n");
- } else {
- printf("Parameter file not stated\n");
- }
- exitcode = 1;
- } else {
- base_filename = basename(par_filename);
- if (!base_filename) {
- if (havezip) {
- printf("Zip file is a directory\n");
- } else {
- printf("Parameter file is a directory\n");
- }
- exitcode = 1;
- }
- }
-
- if (!onlybin) {
- if (!img_filename) {
- printf("Image file not stated\n");
- exitcode = 1;
- } else {
- base_filename = basename(img_filename);
- if (!base_filename) {
- printf("Image file is a directory\n");
- exitcode = 1;
- }
- }
- }
-
- // check for mutually exclusive options
- if ((onlybin) && (havezip)) {
- printf("Option -b and -z are mutually exclusive\n");
- exitcode = 1;
- }
-
- // react on option problems or help request, then exit
- if ((exitcode) || (help)) {
- if (help) {
- printf("This program creates Linksys style images for the WRT350Nv2 router.\n");
- }
- printf(" Usage:\n\
- %s [-h] [-b] [-z] [-i] [-f <version>] [-v] <parameter or zip file> [<image file>]\n\n\
- Options:\n\
- -h - Show this help\n\
- -b - Create only bin file, no img or zip file is created\n\
- -z - Have zip file, the img file will be directly created from it\n\
- -i - Ignore unknown magic numbers\n\
- -f <version> - Wanted firmware version to use with -z\n\
- Default firmware version is 0x2020 = 2.00.20.\n\
- Note: version from parameter file will supersede this\n\
- -v - Increase debug verbosity level\n\n\
- Example:\n\
- %s wrt350nv2.par wrt350nv2.img\n\n", argv[0], argv[0]);
- return exitcode;
- }
-
- // handle special case when zipfile is stated
- if (havezip) {
- zip_filename = par_filename;
- par_filename = NULL;
- }
-
- lprintf(DEBUG_LVL2, " Verbosity: %i\n", verbosity);
- lprintf(DEBUG_LVL2, " Program: %s\n", argv[0]);
-
- if (par_filename) {
- lprintf(DEBUG, "Parameter file: %s\n", par_filename);
- }
- if (zip_filename) {
- lprintf(DEBUG, "Zip file: %s\n", zip_filename);
- }
- if (img_filename) {
- lprintf(DEBUG, "Image file: %s\n", img_filename);
- }
-
-
-// open files from command line
- // parameter/zip file
- if (par_filename) {
- f_par = fopen(par_filename, "rt");
- if (!f_par) {
- exitcode = errno;
- printf("Input file %s: %s\n", par_filename, strerror(exitcode));
- }
- }
-
- // image file
- if (img_filename) {
- f_img = fopen(img_filename, "wb");
- if (!f_img) {
- exitcode = errno;
- printf("Output file %s: %s\n", img_filename, strerror(exitcode));
- }
- }
-
- if (exitcode) {
- return exitcode;
- }
-
-
-// parameter file processing
- if ((!exitcode) && (f_par)) {
- lprintf(DEBUG, "parsing parameter file...\n");
-
- exitcode = parse_par_file(f_par);
-
- lprintf(DEBUG, "...done parsing file\n");
- }
- if (f_par) {
- fclose(f_par);
- }
-
-
-// check all input data
- if ((!exitcode) && (par_filename)) {
- lprintf(DEBUG, "checking mtd data...\n");
-
- for (i = 1; i <= 4; i++) {
- noupdate = 0;
- sizecheck = 0;
- magiccheck = 0;
-
- switch (i) {
- case 1:
- mtd = &mtd_image;
- sizecheck = ROOTFS_END_OFFSET;
- magiccheck = 1;
- break;
- case 2:
- mtd = &mtd_kernel;
- sizecheck = mtd_kernel.size - 16;
- magiccheck = 1;
- break;
- case 3:
- mtd = &mtd_rootfs;
- mtd->offset = mtd_kernel.size;
- mtd->size = ROOTFS_END_OFFSET - mtd_kernel.size;
- sizecheck = PRODUCT_ID_OFFSET - mtd_kernel.size;
- magiccheck = 1;
- break;
- case 4:
- mtd = &mtd_uboot;
- mtd->offset = BOOT_ADDR_BASE_OFF;
- noupdate = 1;
- sizecheck = SN_OFF - BOOT_ADDR_BASE_OFF;
- break;
- default:
- mtd = NULL;
- exitcode = 1;
- printf("unknown mtd check %i\n", i);
- break;
- }
- if (!mtd) {
- break;
- }
-
- lprintf(DEBUG_LVL2, " checking mtd %s\n", mtd->name);
-
- // general checks
-
- // no further checks if no file data present
- if (!mtd->filename) {
- continue;
- }
-
- // not updated by stock firmware
- if (noupdate) {
- printf("mtd %s is specified, but will not be updated as of Linksys firmware 2.0.19\n", mtd->name);
- }
-
- // general magic number check
- magicerror = 0;
- if (magiccheck) {
- switch (i) {
- case 1: // image
- case 2: // kernel
- if (!(
- ((mtd->magic[0] == 0x27) && (mtd->magic[1] == 0x05)) // uImage
- )) {
- magicerror = 1;
- }
- break;
- case 3: // rootfs
- if (!(
- ((mtd->magic[0] == 0x68) && (mtd->magic[1] == 0x73)) // squashfs
- || ((mtd->magic[0] == 0x85) && (mtd->magic[1] == 0x19)) // jffs
- )) {
- magicerror = 1;
- }
- break;
- default:
- magicerror = 1;
- break;
- }
- if (magicerror) {
- printf("mtd %s input file %s has unknown magic number (0x%02X%02X)", mtd->name, mtd->filename, mtd->magic[0], mtd->magic[1]);
- if (ignoremagic) {
- printf("...ignoring");
- } else {
- exitcode = 1;
- }
- printf("\n");
- }
- }
-
- // mtd specific size check
- if (mtd == &mtd_image) {
- if (mtd->filesize < 0x00200000) {
- exitcode = 1;
- printf("mtd %s input file %s too unrealistic small (0x%08lX)\n", mtd->name, mtd->filename, mtd->filesize);
- }
- }
-
- if (mtd == &mtd_kernel) {
- if (mtd->filesize < 0x00080000) {
- exitcode = 1;
- printf("mtd %s input file %s too unrealistic small (0x%08lX)\n", mtd->name, mtd->filename, mtd->filesize);
- }
- }
-
- // general size check
- if (sizecheck) {
- if (sizecheck <= 0) {
- exitcode = 1;
- printf("mtd %s bad file size check (%i) due to input data\n", mtd->name, sizecheck);
- } else {
- if (mtd->filesize > sizecheck) {
- exitcode = 1;
- printf("mtd %s input file %s too big (0x%08lX)\n", mtd->name, mtd->filename, mtd->filesize);
- }
- }
- }
- }
-
- // Check for mandatory parts
- if ((!mtd_image.filename) && (!mtd_kernel.filename || !mtd_rootfs.filename)) {
- exitcode = 1;
- if (mtd_kernel.filename && !mtd_rootfs.filename) {
- printf("Kernel without rootfs, either incorrectly specified or not at all in parameter file\n");
- } else if (!mtd_kernel.filename && mtd_rootfs.filename) {
- printf("Rootfs without kernel, either incorrectly specified or not at all in parameter file\n");
- } else {
- printf("Neither an image nor kernel with rootfs was/were correctly specified or at all in parameter file\n");
- }
- }
-
- // Check for duplicate parts
- if ((mtd_image.filename) && (mtd_kernel.filename || mtd_rootfs.filename)) {
- exitcode = 1;
- printf("Image and kernel/rootfs specified in parameter file\n");
- }
-
- lprintf(DEBUG, "...done checking mtd data\n");
- }
-
-
-// bin creation in memory
- if ((!exitcode) && (par_filename)) {
- bin_filename = "wrt350n.bin";
-
- lprintf(DEBUG, "creating bin file %s...\n", bin_filename);
-
- exitcode = create_bin_file(bin_filename);
-
- lprintf(DEBUG, "...done creating bin file\n");
- }
-
-// zip file creation
- if ((!exitcode) && (!onlybin) && (!zip_filename)) {
- zip_filename = "wrt350n.zip";
-
- lprintf(DEBUG, "creating zip file %s...\n", zip_filename);
-
- exitcode = create_zip_file(zip_filename, bin_filename);
-
- lprintf(DEBUG, "...done creating zip file\n");
- }
-
-
-// img file creation
- if ((!exitcode) && (f_img)) {
- lprintf(DEBUG, "creating img file...\n");
-
- exitcode = create_img_file(f_img, img_filename, zip_filename);
-
- lprintf(DEBUG, "...done creating img file\n");
- }
-
-// clean up
- if (f_img) {
- fclose(f_img);
- }
-
-// end program
- return exitcode;
-}