port the changes from [3155] to Kamikaze
[openwrt.git] / target / utils / src / motorola-bin.c
1 /*
2  * motorola-bin.c
3  *
4  * Copyright (C) 2005-2006 Mike Baker,
5  *                         Imre Kaloz <kaloz@openwrt.org>
6  *                         OpenWrt.org
7  *
8  * $Id$
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  *
24  */
25
26 /*
27  * February 1, 2006
28  *
29  * Add support for for creating WA840G and WE800G images
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <sys/mman.h>
37 #include <string.h>
38 #include <netinet/in.h>
39
40 unsigned long *crc32;
41
42 void init_crc32()
43 {
44     unsigned long crc;
45     unsigned long poly = ntohl(0x2083b8ed);
46     int n, bit;
47     if ((crc32 = (unsigned long *) malloc(256 * sizeof(unsigned long))) == (void *)-1) {
48        perror("malloc");
49        exit(1);
50     }
51     for (n = 0; n < 256; n++) {
52         crc = (unsigned long) n;
53         for (bit = 0; bit < 8; bit++)
54             crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
55         crc32[n] = crc;
56     }
57 }
58
59 unsigned int crc32buf(char *buf, size_t len)
60 {
61     unsigned int crc = 0xFFFFFFFF;
62     for (; len; len--, buf++)
63         crc = crc32[(crc ^ *buf) & 0xff] ^ (crc >> 8);
64     return crc;
65 }
66
67 struct motorola {
68         unsigned int crc;       // crc32 of the remainder
69         unsigned int flags;     // unknown, 105770*
70         char *trx;              // standard trx
71 };
72
73 void usage(void) __attribute__ (( __noreturn__ ));
74
75 void usage(void)
76 {
77         printf("Usage: motorola-bin [-device] [trxfile] [binfile]\n\n");
78         printf("Known devices: 1 - WR850G | 2 - WA840G | 3 - WE800G\n");
79         exit(1);
80 }
81
82 int main(int argc, char **argv)
83 {
84         unsigned int len;
85         int fd;
86         int c;
87         void *trx;
88         struct motorola *firmware;
89
90         // verify parameters
91
92         if (argc!=4)
93         {
94         usage();
95         }
96
97         // mmap trx file
98         if (((fd = open(argv[2], O_RDONLY))  < 0)
99         || ((len = lseek(fd, 0, SEEK_END)) < 0)
100         || ((trx = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1))
101         || (close(fd) < 0)) {
102                 perror("open/malloc");
103                 exit(1);
104         }
105         
106         // create a firmware image in memory
107         // and copy the trx to it
108         firmware = malloc(len+8);
109         memcpy(&firmware->trx,trx,len);
110         munmap(trx,len);
111
112         // setup the motorola headers
113         init_crc32();
114
115         // setup the firmware magic
116
117         while ((c = getopt(argc, argv, "123")) !=-1) {
118                 switch (c) {
119                         case '1':
120                                 firmware->flags = ntohl(0x10577050); // Motorola WR850G
121                                 break;
122                         case '2':
123                                 firmware->flags = ntohl(0x10577040); // Motorola WA840G
124                                 break;
125                         case '3':
126                                 firmware->flags = ntohl(0x10577000); // Motorola WE800G
127                                 break;
128                         default:
129                                 usage();
130                 }
131         }
132
133         firmware->crc   = htonl(crc32buf((char *)&firmware->flags,len+4));
134
135         // write the firmware
136         if (((fd = open(argv[3], O_CREAT|O_WRONLY,0644)) < 0)
137         || (write(fd,firmware,len+8) != len+8)
138         || (close(fd) < 0)) {
139                 perror("write");
140                 exit(-1);
141         }
142
143         free(firmware);
144
145         return 0;
146 }