6 #include <asm/byteorder.h>
11 #define DBG(...) {printf(__VA_ARGS__); }
16 #define ERR(...) {printf(__VA_ARGS__); }
17 #define ALIGN(a,b) ((a) + ((b) - ((a) % (b))))
18 #define ROOTFS_ALIGN 128
19 #define HEADER_SIZE 71
22 * Fw Header Layout for Netgear / Sercomm devices (bytes)
24 * Size : 512 bytes + zipped image size
31 * swVer : 55-62 uint32_t in BE
33 * ChkSum : 511 Inverse value of the full image checksum while this location is 0x00
36 static const char* magic
= "sErCoMm"; /* 7 */
38 /* 7-11: version control/download control ? */
39 static const unsigned char version
[4] = { 0x00, 0x01, 0x00, 0x00 };
42 /* 512 onwards -> ZIP containing rootfs with the same Header */
45 char* file_name
; /* name of the file */
46 char* file_data
; /* data of the file in memory */
47 u_int32_t file_size
; /* length of the file */
50 static u_int8_t
getCheckSum(char* data
, int len
) {
54 ERR("Invalid pointer provided!\n");
58 for (int i
= 0; i
< len
; i
++) {
65 static int bufferFile(struct file_info
* finfo
) {
69 if (!finfo
|| !finfo
->file_name
) {
70 ERR("Invalid pointer provided!\n");
74 DBG("Opening file: %s\n", finfo
->file_name
);
76 if (!(fp
= fopen(finfo
->file_name
, "rb"))) {
77 ERR("Error opening file: %s\n", finfo
->file_name
);
83 fseek(fp
, 0L, SEEK_END
);
88 ERR("Error getting filesize: %s\n", finfo
->file_name
);
93 DBG("Filesize: %i\n", fs
);
94 finfo
->file_size
= fs
;
96 if (!(finfo
->file_data
= malloc(fs
))) {
97 ERR("Out of memory!\n");
102 if (fread(finfo
->file_data
, 1, fs
, fp
) != fs
) {
103 ERR("Error reading file %s\n", finfo
->file_name
);
108 DBG("File: read successful\n");
114 static int writeFile(struct file_info
* finfo
) {
117 if (!finfo
|| !finfo
->file_name
) {
118 ERR("Invalid pointer provided!\n");
122 DBG("Opening file: %s\n", finfo
->file_name
);
124 if (!(fp
= fopen(finfo
->file_name
, "w"))) {
125 ERR("Error opening file: %s\n", finfo
->file_name
);
129 DBG("Writing file: %s\n", finfo
->file_name
);
131 if (fwrite(finfo
->file_data
, 1, finfo
->file_size
, fp
) != finfo
->file_size
) {
132 ERR("Wanted to write, but something went wrong!\n");
141 static void fi_clean(struct file_info
* finfo
) {
145 if (finfo
->file_name
) {
146 finfo
->file_name
= NULL
;
149 if (finfo
->file_data
) {
150 free(finfo
->file_data
);
151 finfo
->file_data
= NULL
;
154 finfo
->file_size
= 0;
157 static void usage(char* argv
[]) {
158 printf("Usage: %s <sysupgradefile> <kernel_offset> <HWID> <HWVER> <SWID>\n"
159 "All are positional arguments ... \n"
160 " sysupgradefile: File with the kernel uimage at 0\n"
161 " kernel_offset: Offset where the kernel is located (decimal, hex or octal notation)\n"
162 " HWID: Hardware ID, ASCII\n"
163 " HWVER: Hardware Version, ASCII\n"
164 " SWID: Software Version (decimal, hex or octal notation)\n"
169 int main(int argc
, char* argv
[]) {
174 u_int32_t kernel_offset
= 0x90000; /* offset for the kernel inside the rootfs, default val */
176 struct file_info sysupgrade
= { 0 };
177 struct file_info header
= { 0 };
178 struct file_info rootfs
= { 0 };
179 struct file_info zippedfs
= { 0 };
180 struct file_info image
= { 0 };
183 char* rootfsname
= NULL
;
184 char* zipfsname
= NULL
;
189 struct file_info myfile
= { argv
[1], 0, 0 };
191 if (bufferFile(&myfile
))
194 chkSum
= getCheckSum(myfile
.file_data
, myfile
.file_size
);
195 printf("Checksum for File: 0x%hhX\n", chkSum
);
205 printf("Building fw image for sercomm devices ..\n");
211 sysupgrade
.file_name
= argv
[1];
212 image
.file_name
= argv
[1];
213 kernel_offset
= (u_int32_t
) strtol(argv
[2], NULL
, 0);
214 swVer
= (u_int32_t
) strtol(argv
[5], NULL
, 0);
215 swVer
= __cpu_to_be32(swVer
);
217 /* Check if files actually exist */
218 if (access(sysupgrade
.file_name
, (F_OK
| R_OK
))) {
220 ERR("File not found: %s\n", sysupgrade
.file_name
);
224 /* Calculate amount of required memory (incl. 0-term) */
225 rootfsname_sz
= strlen(sysupgrade
.file_name
) + 7 + 1;
226 zipfsname_sz
= strlen(sysupgrade
.file_name
) + 7 + 4 + 1;
228 /* Allocate required memory */
229 if (!(rootfsname
= (char*) malloc(rootfsname_sz
)) || !(zipfsname
=
230 (char*) malloc(zipfsname_sz
))) {
232 ERR("Out of memory!\n");
236 /* Create filenames */
237 if (snprintf(rootfsname
, rootfsname_sz
, "%s.rootfs", sysupgrade
.file_name
)
239 || snprintf(zipfsname
, zipfsname_sz
, "%s.rootfs.zip",
240 sysupgrade
.file_name
) >= zipfsname_sz
) {
242 ERR("Buffer too small!\n");
246 /* Buffer all files */
247 if (bufferFile(&sysupgrade
)) {
252 DBG("Building header: %s %s %2X %s\n", hwID
, hwVer
, swVer
, magic
);
254 /* Construct the firmware header/magic */
255 header
.file_name
= NULL
;
256 header
.file_size
= HEADER_SIZE
;
258 if (!(header
.file_data
= (char*) calloc(1, HEADER_SIZE
))) {
260 ERR("Out of memory!\n");
264 strncpy(header
.file_data
+ 0, magic
, 7);
265 memcpy(header
.file_data
+ 7, version
, sizeof(version
));
266 strncpy(header
.file_data
+ 11, hwID
, 34);
267 strncpy(header
.file_data
+ 45, hwVer
, 10);
268 memcpy(header
.file_data
+ 55, &swVer
, sizeof(swVer
));
269 strncpy(header
.file_data
+ 63, magic
, 7);
271 DBG("Creating rootfs ..\n");
273 /* Construct a rootfs */
274 rootfs
.file_name
= rootfsname
;
275 rootfs
.file_size
= ALIGN(
276 sysupgrade
.file_size
+ kernel_offset
+ header
.file_size
,
279 if (!(rootfs
.file_data
= calloc(1, rootfs
.file_size
))) {
281 ERR("Out of memory!\n");
285 /* copy Owrt image to kernel location */
286 memcpy(rootfs
.file_data
+ kernel_offset
, sysupgrade
.file_data
,
287 sysupgrade
.file_size
);
289 /* Append header after the owrt image. The updater searches for it */
290 memcpy(rootfs
.file_data
+ kernel_offset
+ sysupgrade
.file_size
,
291 header
.file_data
, header
.file_size
);
294 if (writeFile(&rootfs
)) {
299 /* Construct a zip */
300 DBG("Preparing to zip ..\n");
302 /* now that we got the rootfs, repeat the whole thing again(sorta):
303 * 1. zip the rootfs */
304 zipcmd_sz
= 3 + 1 + strlen(zipfsname
) + 1 + strlen(rootfs
.file_name
) + 1;
306 if (!(zipcmd
= malloc(zipcmd_sz
))) {
308 ERR("Out of memory!\n");
312 if (snprintf(zipcmd
, zipcmd_sz
, "%s %s %s", "zip", zipfsname
,
313 rootfs
.file_name
) >= zipcmd_sz
) {
315 ERR("Buffer too small!\n");
319 if (system(zipcmd
)) {
321 ERR("Error creating a zip file!\n");
325 /* and load zipped fs */
326 zippedfs
.file_name
= zipfsname
;
328 if (bufferFile(&zippedfs
)) {
333 DBG("Creating Image.\n");
335 /* 2. create new file 512 + rootfs size */
336 image
.file_size
= zippedfs
.file_size
+ 512;
337 if (!(image
.file_data
= malloc(zippedfs
.file_size
+ 512))) {
339 ERR("Out of memory!\n");
343 /* 3. add header to file */
344 memcpy(image
.file_data
, header
.file_data
, header
.file_size
);
346 /* 4. clear remaining space */
347 if (header
.file_size
< 512)
348 memset(image
.file_data
+ header
.file_size
, 0, 512 - header
.file_size
);
350 /* 5. copy zipfile at loc 512 */
351 memcpy(image
.file_data
+ 512, zippedfs
.file_data
, zippedfs
.file_size
);
353 /* 6. do a checksum run, and compute checksum */
354 chkSum
= getCheckSum(image
.file_data
, image
.file_size
);
356 DBG("Checksum for Image: %hhX\n", chkSum
);
358 /* 7. write the checksum inverted into byte 511 to bring it to 0 on verification */
359 chkSum
= (chkSum
^ 0xFF) + 1;
360 image
.file_data
[511] = (char) chkSum
;
362 chkSum
= getCheckSum(image
.file_data
, image
.file_size
);
363 DBG("Checksum for after fix: %hhX\n", chkSum
);
366 ERR("Invalid checksum!\n")
370 /* 8. pray that the updater will accept the file */
371 if (writeFile(&image
)) {
381 if (rootfs
.file_name
&& !access(rootfs
.file_name
, F_OK
| W_OK
))
382 remove(rootfs
.file_name
);
384 if (zippedfs
.file_name
&& !access(zippedfs
.file_name
, F_OK
| W_OK
))
385 remove(zippedfs
.file_name
);
387 fi_clean(&sysupgrade
);