9 #if !defined(__BYTE_ORDER)
10 #error "Unknown byte order"
13 #if __BYTE_ORDER == __BIG_ENDIAN
14 #define cpu_to_be32(x) (x)
15 #define be32_to_cpu(x) (x)
16 #define cpu_to_be16(x) (x)
17 #define be16_to_cpu(x) (x)
18 #elif __BYTE_ORDER == __LITTLE_ENDIAN
19 #define cpu_to_be32(x) bswap_32(x)
20 #define be32_to_cpu(x) bswap_32(x)
21 #define cpu_to_be16(x) bswap_16(x)
22 #define be16_to_cpu(x) bswap_16(x)
24 #error "Unsupported endianness"
30 #define DBG(...) {printf(__VA_ARGS__); }
35 #define ERR(...) {printf(__VA_ARGS__); }
36 #define ALIGN(a,b) ((a) + ((b) - ((a) % (b))))
37 #define ROOTFS_ALIGN 128
38 #define HEADER_SIZE 71
41 * Fw Header Layout for Netgear / Sercomm devices (bytes)
43 * Size : 512 bytes + zipped image size
50 * swVer : 55-62 uint32_t in BE
52 * ChkSum : 511 Inverse value of the full image checksum while this location is 0x00
55 static const char* magic
= "sErCoMm"; /* 7 */
57 /* 7-11: version control/download control ? */
58 static const unsigned char version
[4] = { 0x00, 0x01, 0x00, 0x00 };
61 /* 512 onwards -> ZIP containing rootfs with the same Header */
64 char* file_name
; /* name of the file */
65 char* file_data
; /* data of the file in memory */
66 u_int32_t file_size
; /* length of the file */
69 static u_int8_t
getCheckSum(char* data
, int len
) {
73 ERR("Invalid pointer provided!\n");
77 for (int i
= 0; i
< len
; i
++) {
84 static int bufferFile(struct file_info
* finfo
) {
88 if (!finfo
|| !finfo
->file_name
) {
89 ERR("Invalid pointer provided!\n");
93 DBG("Opening file: %s\n", finfo
->file_name
);
95 if (!(fp
= fopen(finfo
->file_name
, "rb"))) {
96 ERR("Error opening file: %s\n", finfo
->file_name
);
102 fseek(fp
, 0L, SEEK_END
);
107 ERR("Error getting filesize: %s\n", finfo
->file_name
);
112 DBG("Filesize: %i\n", fs
);
113 finfo
->file_size
= fs
;
115 if (!(finfo
->file_data
= malloc(fs
))) {
116 ERR("Out of memory!\n");
121 if (fread(finfo
->file_data
, 1, fs
, fp
) != fs
) {
122 ERR("Error reading file %s\n", finfo
->file_name
);
127 DBG("File: read successful\n");
133 static int writeFile(struct file_info
* finfo
) {
136 if (!finfo
|| !finfo
->file_name
) {
137 ERR("Invalid pointer provided!\n");
141 DBG("Opening file: %s\n", finfo
->file_name
);
143 if (!(fp
= fopen(finfo
->file_name
, "w"))) {
144 ERR("Error opening file: %s\n", finfo
->file_name
);
148 DBG("Writing file: %s\n", finfo
->file_name
);
150 if (fwrite(finfo
->file_data
, 1, finfo
->file_size
, fp
) != finfo
->file_size
) {
151 ERR("Wanted to write, but something went wrong!\n");
160 static void fi_clean(struct file_info
* finfo
) {
164 if (finfo
->file_name
) {
165 finfo
->file_name
= NULL
;
168 if (finfo
->file_data
) {
169 free(finfo
->file_data
);
170 finfo
->file_data
= NULL
;
173 finfo
->file_size
= 0;
176 static void usage(char* argv
[]) {
177 printf("Usage: %s <sysupgradefile> <kernel_offset> <HWID> <HWVER> <SWID>\n"
178 "All are positional arguments ... \n"
179 " sysupgradefile: File with the kernel uimage at 0\n"
180 " kernel_offset: Offset where the kernel is located (decimal, hex or octal notation)\n"
181 " HWID: Hardware ID, ASCII\n"
182 " HWVER: Hardware Version, ASCII\n"
183 " SWID: Software Version (decimal, hex or octal notation)\n"
188 int main(int argc
, char* argv
[]) {
193 u_int32_t kernel_offset
= 0x90000; /* offset for the kernel inside the rootfs, default val */
195 struct file_info sysupgrade
= { 0 };
196 struct file_info header
= { 0 };
197 struct file_info rootfs
= { 0 };
198 struct file_info zippedfs
= { 0 };
199 struct file_info image
= { 0 };
202 char* rootfsname
= NULL
;
203 char* zipfsname
= NULL
;
208 struct file_info myfile
= { argv
[1], 0, 0 };
210 if (bufferFile(&myfile
))
213 chkSum
= getCheckSum(myfile
.file_data
, myfile
.file_size
);
214 printf("Checksum for File: 0x%hhX\n", chkSum
);
224 printf("Building fw image for sercomm devices ..\n");
230 sysupgrade
.file_name
= argv
[1];
231 image
.file_name
= argv
[1];
232 kernel_offset
= (u_int32_t
) strtol(argv
[2], NULL
, 0);
233 swVer
= (u_int32_t
) strtol(argv
[5], NULL
, 0);
234 swVer
= cpu_to_be32(swVer
);
236 /* Check if files actually exist */
237 if (access(sysupgrade
.file_name
, (F_OK
| R_OK
))) {
239 ERR("File not found: %s\n", sysupgrade
.file_name
);
243 /* Calculate amount of required memory (incl. 0-term) */
244 rootfsname_sz
= strlen(sysupgrade
.file_name
) + 7 + 1;
245 zipfsname_sz
= strlen(sysupgrade
.file_name
) + 7 + 4 + 1;
247 /* Allocate required memory */
248 if (!(rootfsname
= (char*) malloc(rootfsname_sz
)) || !(zipfsname
=
249 (char*) malloc(zipfsname_sz
))) {
251 ERR("Out of memory!\n");
255 /* Create filenames */
256 if (snprintf(rootfsname
, rootfsname_sz
, "%s.rootfs", sysupgrade
.file_name
)
258 || snprintf(zipfsname
, zipfsname_sz
, "%s.rootfs.zip",
259 sysupgrade
.file_name
) >= zipfsname_sz
) {
261 ERR("Buffer too small!\n");
265 /* Buffer all files */
266 if (bufferFile(&sysupgrade
)) {
271 DBG("Building header: %s %s %2X %s\n", hwID
, hwVer
, swVer
, magic
);
273 /* Construct the firmware header/magic */
274 header
.file_name
= NULL
;
275 header
.file_size
= HEADER_SIZE
;
277 if (!(header
.file_data
= (char*) calloc(1, HEADER_SIZE
))) {
279 ERR("Out of memory!\n");
283 strncpy(header
.file_data
+ 0, magic
, 7);
284 memcpy(header
.file_data
+ 7, version
, sizeof(version
));
285 strncpy(header
.file_data
+ 11, hwID
, 34);
286 strncpy(header
.file_data
+ 45, hwVer
, 10);
287 memcpy(header
.file_data
+ 55, &swVer
, sizeof(swVer
));
288 strncpy(header
.file_data
+ 63, magic
, 7);
290 DBG("Creating rootfs ..\n");
292 /* Construct a rootfs */
293 rootfs
.file_name
= rootfsname
;
294 rootfs
.file_size
= ALIGN(
295 sysupgrade
.file_size
+ kernel_offset
+ header
.file_size
,
298 if (!(rootfs
.file_data
= calloc(1, rootfs
.file_size
))) {
300 ERR("Out of memory!\n");
304 /* copy Owrt image to kernel location */
305 memcpy(rootfs
.file_data
+ kernel_offset
, sysupgrade
.file_data
,
306 sysupgrade
.file_size
);
308 /* Append header after the owrt image. The updater searches for it */
309 memcpy(rootfs
.file_data
+ kernel_offset
+ sysupgrade
.file_size
,
310 header
.file_data
, header
.file_size
);
313 if (writeFile(&rootfs
)) {
318 /* Construct a zip */
319 DBG("Preparing to zip ..\n");
321 /* now that we got the rootfs, repeat the whole thing again(sorta):
322 * 1. zip the rootfs */
323 zipcmd_sz
= 3 + 1 + strlen(zipfsname
) + 1 + strlen(rootfs
.file_name
) + 1;
325 if (!(zipcmd
= malloc(zipcmd_sz
))) {
327 ERR("Out of memory!\n");
331 if (snprintf(zipcmd
, zipcmd_sz
, "%s %s %s", "zip", zipfsname
,
332 rootfs
.file_name
) >= zipcmd_sz
) {
334 ERR("Buffer too small!\n");
338 if (system(zipcmd
)) {
340 ERR("Error creating a zip file!\n");
344 /* and load zipped fs */
345 zippedfs
.file_name
= zipfsname
;
347 if (bufferFile(&zippedfs
)) {
352 DBG("Creating Image.\n");
354 /* 2. create new file 512 + rootfs size */
355 image
.file_size
= zippedfs
.file_size
+ 512;
356 if (!(image
.file_data
= malloc(zippedfs
.file_size
+ 512))) {
358 ERR("Out of memory!\n");
362 /* 3. add header to file */
363 memcpy(image
.file_data
, header
.file_data
, header
.file_size
);
365 /* 4. clear remaining space */
366 if (header
.file_size
< 512)
367 memset(image
.file_data
+ header
.file_size
, 0, 512 - header
.file_size
);
369 /* 5. copy zipfile at loc 512 */
370 memcpy(image
.file_data
+ 512, zippedfs
.file_data
, zippedfs
.file_size
);
372 /* 6. do a checksum run, and compute checksum */
373 chkSum
= getCheckSum(image
.file_data
, image
.file_size
);
375 DBG("Checksum for Image: %hhX\n", chkSum
);
377 /* 7. write the checksum inverted into byte 511 to bring it to 0 on verification */
378 chkSum
= (chkSum
^ 0xFF) + 1;
379 image
.file_data
[511] = (char) chkSum
;
381 chkSum
= getCheckSum(image
.file_data
, image
.file_size
);
382 DBG("Checksum for after fix: %hhX\n", chkSum
);
385 ERR("Invalid checksum!\n")
389 /* 8. pray that the updater will accept the file */
390 if (writeFile(&image
)) {
400 if (rootfs
.file_name
&& !access(rootfs
.file_name
, F_OK
| W_OK
))
401 remove(rootfs
.file_name
);
403 if (zippedfs
.file_name
&& !access(zippedfs
.file_name
, F_OK
| W_OK
))
404 remove(zippedfs
.file_name
);
406 fi_clean(&sysupgrade
);