ccd5d67a87dc85c5accb80e96c440f5a01fc4be0
[openwrt/openwrt.git] / tools / firmware-utils / src / mksercommfw.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5
6 /* #define DEBUG 1 */
7
8 /*
9 * Fw Header Layout for Netgear / Sercomm devices
10 * */
11 static const char *magic = "sErCoMm"; /* 7 */
12 /* 7-11: version control/download control ? */
13 unsigned char version[4] = {0x00, 0x01, 0x00, 0x00};
14 char *hwID = ""; /* 11-43 , ASCII/HEX */
15 char *hwVer = ""; /* 44-57 , ASCII/HEX */
16 char *swVer = ""; /* 58-62 , ASCII/HEX */
17 /* magic again. */
18
19 #define HEADER_SIZE 71
20
21 /* null bytes until 511 */
22 u_int32_t checksum = 0xFF; /* checksum */
23 /* 512 onwards -> ZIP containing rootfs with the same Header */
24
25
26 /* appended on rootfs for the Header. */
27 const int footer_size = 128;
28
29 struct file_info {
30 char *file_name; /* name of the file */
31 char *file_data; /* data of the file in memory */
32 u_int32_t file_size; /* length of the file */
33 };
34
35 u_int8_t getCheckSum(char *data, int len)
36 {
37
38 int32_t previous = 0;
39 u_int32_t new = 0;
40
41 for (u_int32_t i = 0; i < len; i++) {
42 new = (data[i] + previous) % 256;
43 previous = new | previous & -256;
44 }
45 return (u_int8_t) new;
46 }
47
48 void *bufferFile(struct file_info *finfo, int dontload)
49 {
50 int fs = 0;
51 FILE *f = NULL;
52
53 #ifdef DEBUG
54 printf("Opening file: %s\n", finfo->file_name);
55 #endif
56 f = fopen(finfo->file_name, "rb");
57 if (f == NULL) {
58 perror("Error");
59 exit(1);
60 }
61
62 fseek(f, 0L, SEEK_END);
63 fs = ftell(f);
64 rewind(f);
65
66 #ifdef DEBUG
67 printf("Filesize: %i .\n", fs);
68 #endif
69
70 finfo->file_size = fs;
71
72 if (dontload) {
73 return 0;
74 }
75
76 char *data = malloc(fs);
77 finfo->file_data = data;
78
79 int read = fread(data, fs, 1, f);
80
81 if (read != 1) {
82 printf("Error reading file %s.", finfo->file_name);
83 exit(1);
84 }
85
86 #ifdef DEBUG
87 printf("File: read successfully %i bytes.\n", read*fs);
88 #endif
89 fclose(f);
90 }
91
92 void *writeFile(struct file_info *finfo)
93 {
94
95 #ifdef DEBUG
96 printf("Writing file: %s.\n", finfo->file_name);
97 #endif
98
99 FILE *fout = fopen(finfo->file_name, "w");
100
101 if (!fwrite(finfo->file_data, finfo->file_size, 1, fout)) {
102 printf("Wanted to write, but something went wrong.\n");
103 fclose(fout);
104 exit(1);
105 }
106 fclose(fout);
107 }
108
109 void *rmFile(struct file_info *finfo)
110 {
111 remove(finfo->file_name);
112 free(finfo->file_data);
113 finfo->file_size = 0;
114 }
115
116 void *usage(char *argv[])
117 {
118 printf("Usage: %s <sysupgradefile> <kernel_offset> <HWID> <HWVER> <SWID>\n"
119 "All are positional arguments ... \n"
120 " sysupgradefile: File with the kernel uimage at 0\n"
121 " kernel_offset: Offset in Hex where the kernel is located\n"
122 " HWID: Hardware ID, ASCII\n"
123 " HWVER: Hardware Version, ASCII\n"
124 " SWID: Software Version, Hex\n"
125 " \n"
126 " ", argv[0]);
127 }
128
129 int main(int argc, char *argv[])
130 {
131 printf("Building fw image for sercomm devices.\n");
132
133 if (argc == 2) {
134 struct file_info myfile = {argv[1], 0, 0};
135 bufferFile(&myfile, 0);
136 char chksum = getCheckSum(myfile.file_data, myfile.file_size);
137 printf("Checksum for File: %X.\n", chksum);
138 return 0;
139 }
140
141 if (argc != 6) {
142 usage(argv);
143 return 1;
144 }
145
146 /* Args */
147
148 struct file_info sysupgrade = {argv[1], 0, 0};
149 bufferFile(&sysupgrade, 0);
150
151 int kernel_offset = 0x90000; /* offset for the kernel inside the rootfs, default val */
152 sscanf(argv[2], "%X", &kernel_offset);
153 #ifdef DEBUG
154 printf("Kernel_offset: at %X/%i bytes.\n", kernel_offset, kernel_offset);
155 #endif
156 char *hwID = argv[3];
157 char *hwVer = argv[4];
158 u_int32_t swVer = 0;
159 sscanf(argv[5],"%4X",&swVer);
160 swVer = bswap_32(swVer);
161
162 char *rootfsname = malloc(2*strlen(sysupgrade.file_name) + 8);
163 sprintf(rootfsname, "%s.rootfs", sysupgrade.file_name);
164
165 char *zipfsname = malloc(2*strlen(rootfsname) + 5);
166 sprintf(zipfsname, "%s.zip", rootfsname);
167 /* / Args */
168
169 #ifdef DEBUG
170 printf("Building header: %s %s %2X %s.\n", hwID , hwVer, swVer, magic);
171 #endif
172 /* Construct the firmware header/magic */
173 struct file_info header = {0, 0, 0};
174 header.file_size = HEADER_SIZE;
175 header.file_data = malloc(HEADER_SIZE);
176 bzero(header.file_data, header.file_size);
177
178 char *tg = header.file_data;
179 strcpy(tg, magic);
180 memcpy(tg+7, version, 4*sizeof(char));
181 strcpy(tg+11, hwID);
182 strcpy(tg+45, hwVer);
183 memcpy(tg+55, &swVer,sizeof(u_int32_t));
184 strcpy(tg+63, magic);
185
186 #ifdef DEBUG
187 printf("Header done, now creating rootfs.");
188 #endif
189 /* Construct a rootfs */
190 struct file_info rootfs = {0, 0, 0};
191 rootfs.file_size = sysupgrade.file_size + kernel_offset + footer_size;
192 rootfs.file_data = malloc(rootfs.file_size);
193 bzero(rootfs.file_data, rootfs.file_size);
194 rootfs.file_name = rootfsname;
195
196 /* copy Owrt image to Kernel location */
197 memcpy(rootfs.file_data+kernel_offset, sysupgrade.file_data, sysupgrade.file_size);
198
199 /* 22 added to get away from sysup image, no other reason.
200 * updater searches for magic anyway */
201 tg = rootfs.file_data + kernel_offset + sysupgrade.file_size+22;
202
203 memcpy(tg, header.file_data, header.file_size);
204 writeFile(&rootfs);
205
206 #ifdef DEBUG
207 printf("Preparing to zip.\n");
208 #endif
209 /* now that we got the rootfs, repeat the whole thing again(sorta):
210 * 1. zip the rootfs */
211 char *zipper = malloc(5 + 2*strlen(rootfs.file_name) + 6);
212 sprintf(zipper, "%s %s %s", "zip ", zipfsname, rootfs.file_name);
213 int ret = system(zipper);
214
215 /* clear rootfs file */
216 rmFile(&rootfs);
217
218 /* and load zipped fs */
219 struct file_info zippedfs = {zipfsname, 0, 0};
220 bufferFile(&zippedfs, 0);
221
222 #ifdef DEBUG
223 printf("Creating Image.\n");
224 #endif
225
226 /* 2. create new file 512+rootfs size */
227 struct file_info image = {argv[1], 0, 0};
228 image.file_data = malloc(zippedfs.file_size + 512);
229 image.file_size = zippedfs.file_size + 512;
230
231 /* 3. copy zipfile at loc 512 */
232 memcpy(image.file_data+512, zippedfs.file_data, zippedfs.file_size);
233 rmFile(&zippedfs);
234
235 /* 4. add header to file */
236 memcpy(image.file_data, header.file_data, header.file_size);
237
238 /* 5. do a checksum run, and compute checksum */
239 char chksum = getCheckSum(image.file_data, image.file_size);
240 #ifdef DEBUG
241 printf("Checksum for Image: %X.\n", chksum);
242 #endif
243
244 /* 6. write the checksum invert into byte 511 to bring it to 0 */
245 chksum = (chksum ^ 0xFF) + 1;
246 memcpy(image.file_data+511, &chksum, 1);
247
248 chksum = getCheckSum(image.file_data, image.file_size);
249 #ifdef DEBUG
250 printf("Checksum for after fix: %X.\n", chksum);
251 #endif
252 /* 7. pray that the updater will accept the file */
253 writeFile(&image);
254 return 0;
255 }