Fix airlink image generation tool
[openwrt/svn-archive/archive.git] / tools / firmware-utils / src / airlink.c
index 9b1016da72ab69a3aabbcf2aa33f1730943110cb..657c971761f6960b4a54303c4b5197994ee609f6 100644 (file)
@@ -17,11 +17,13 @@ AIRLINK AR525W firmware image structure
 *****************************************************************************/
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <netinet/in.h>
 
 typedef unsigned long u32;
 typedef unsigned char uchar;
@@ -108,7 +110,6 @@ int generate_image(char *kname, char *fsname, char *fname, int EHDR)
        u32 lenk, lens;
        uchar *bk, *bs;
        int fkd, ffd, fsd;
-       int pad = 0x1f;
        fkd = open(kname, O_RDONLY);
        ffd = creat(fname, 0x644);
        if ((fkd < 0) || (ffd < 0))
@@ -135,12 +136,11 @@ int generate_image(char *kname, char *fsname, char *fname, int EHDR)
        else
                write(ffd, header + 2, 0x20);
        write(ffd, bk, lenk);
-       if (fsname && JFFS2)
-               pad = 0xffff;
+       if (!JFFS2) JFFS2 = 0x20;
        printf("Padding header+kernel - 0x%x +  0x%x = 0x%x\n",
-              lenk + 0x20, ((lenk + 0x20) | pad) + 1 - lenk - 0x20,
-              ((lenk + 0x20) | pad) + 1);
-       for (i = 0; i < ((lenk + 0x20) | pad) + 1 - lenk - 0x20; i++)
+              lenk, ((lenk - 1 + JFFS2) / JFFS2) * JFFS2 - lenk,
+              ((lenk - 1 + JFFS2) / JFFS2) * JFFS2);
+       for (i = 0; i < ((lenk - 1 + JFFS2) / JFFS2) * JFFS2 - lenk; i++)
                write(ffd, header, 1);
        if (fsname) {
                write(ffd, bs, lens);
@@ -169,13 +169,13 @@ void usage(char *prog)
        printf("Usage: %s [-b 0/1] image_filename \n", prog);
        printf("       update checksums for firmware file\n");
        printf
-           ("Usage: %s [-b 0/1] [-j] [-e] kernel filesystem image_filename \n",
+           ("Usage: %s [-b 0/1] [-j erasesize_in_kibytes] [-e] kernel filesystem image_filename \n",
             prog);
        printf("       generate firmware file and update checksums\n");
        printf("--------------------------------------------------\n");
        printf("       -e - generate header for web upload\n");
-       printf("       -j - generate header for jffs2 filesystem\n");
        printf("       -b 0/1 - clear/update bootloader checksum\n");
+       printf("       -j erasesize_in_kibytes - generate header for jffs2 filesystem\n");
 }
 
 int main(int argc, char **argv)
@@ -187,7 +187,7 @@ int main(int argc, char **argv)
        extern char *optarg;
        extern int optind, optopt;
 
-       while ((c = getopt(argc, argv, "b:e:j")) != -1) {
+       while ((c = getopt(argc, argv, "b:ej:")) != -1) {
                switch (c) {
                case 'b':
                        if (optarg[0] == '1')
@@ -197,7 +197,8 @@ int main(int argc, char **argv)
                        EHDR = 1;
                        break;
                case 'j':
-                       JFFS2 = 1;
+                       sscanf(optarg, "%i", &JFFS2);
+                       JFFS2 *= 1024;
                        break;
                case '?':
                        fprintf(stderr, "\nError: unknown arg %c\n\n\n",
@@ -242,29 +243,36 @@ int main(int argc, char **argv)
        uchar *buf = malloc(len);
        read(fd, buf, len);
        u32 sum, l0;
-       u32 MagicS = 0x4b544d47;
-       u32 MagicE = 0x4e525241;
-       if (*((u32 *) buf) == MagicS) {
+       u32 MagicS = 0x474d544b;
+       u32 MagicE = 0x4152524e;
+       if (ntohl(*((u32 *) buf)) == MagicS) {
                fprintf(stderr,
                        "Image without extra 8 bytes - Standard header\n");
-               *((u32 *) (buf + 0x10)) = len;
+               buf[0x10] = len & 0xff;
+               buf[0x11] = (len >> 8) & 0xff;
+               buf[0x12] = (len >> 16) & 0xff;
+               buf[0x13] = (len >> 24) & 0xff;
                lseek(fd, 0x10, SEEK_SET);
                write(fd, buf + 0x10, 0x4);
                EHDR = 0;
-       } else if ((*((u32 *) (buf + 0x8)) == MagicS)
-                  && ((*((u32 *) (buf + 0x4)) == MagicE))) {
+       } else if ((ntohl(*((u32 *) (buf + 0x8))) == MagicS)
+                  && ((ntohl(*((u32 *) (buf + 0x4))) == MagicE))) {
                fprintf(stderr,
                        "Image with extra 8 bytes - Extended header\n");
                *((u32 *) (buf + 0x18)) = len - 8;
+               buf[0x18] = (len - 8) & 0xff;
+               buf[0x19] = ((len - 8) >> 8) & 0xff;
+               buf[0x1a] = ((len - 8) >> 16) & 0xff;
+               buf[0x1b] = ((len - 8) >> 24) & 0xff;
                lseek(fd, 0x18, SEEK_SET);
                write(fd, buf + 0x18, 0x4);
                buf += 8;
                EHDR = 1;
-       } else if (len == *((u32 *) (buf + 0x10))) {
+       } else if (len == buf[0x10] | ((u32)buf[0x11] << 8) | ((u32)buf[0x12] << 16) | ((u32)buf[0x13] << 24)) {
                fprintf(stderr,
                        "Image without extra 8 bytes - Standard header\n");
                EHDR = 0;
-       } else if (len == *((u32 *) (buf + 0x18)) + 8) {
+       } else if (len == (buf[0x18] | ((u32)buf[0x19] << 8) | ((u32)buf[0x1a] << 16) | ((u32)buf[0x1b] << 24)) + 8) {
                fprintf(stderr,
                        "Image with extra 8 bytes - Extended header\n");
                buf += 8;
@@ -273,18 +281,15 @@ int main(int argc, char **argv)
                fprintf(stderr, "ERROR: Wrong image size\n");
                exit(-1);
        }
-       l0 = *((u32 *) & buf[0x10]);
+       l0 = buf[0x10] | ((u32)buf[0x11] << 8) | ((u32)buf[0x12] << 16) | ((u32)buf[0x13] << 24);
        if (!BHDR)
                *((u32 *) & buf[0x18]) = 0;
-       unsigned long sum0 = *((u32 *) & buf[0x18]);
-       unsigned long sum1 = *((u32 *) & buf[0x4]);
+       unsigned long sum0 = buf[0x18] | ((u32)buf[0x19] << 8) | ((u32)buf[0x1a] << 16) | ((u32)buf[0x1b] << 24);
+       unsigned long sum1 = buf[0x4] | ((u32)buf[0x5] << 8) | ((u32)buf[0x6] << 16) | ((u32)buf[0x7] << 24);
        *((u32 *) & buf[0x4]) = 0x0L;
-       for (i = 0; i < 0x100; i++)
-               b[i] = buf[i];
-       for (i = 0; i < 0x100; i++)
-               b[0x100 + i] = buf[(l0 >> 1) + i];
-       for (i = 0; i < 0x200; i++)
-               b[0x200 + i] = buf[l0 - 0x200 + i];
+       memcpy(b, buf, 0x100);
+       memcpy(b + 0x100, buf + ((l0 >> 1) - ((l0 & 0x6) >> 1)), 0x100);
+       memcpy(b + 0x200, buf + (l0 - 0x200), 0x200);
        *((u32 *) & b[0x18]) = 0x0L;
 
        sum = crc32(b, 0x400);
@@ -293,10 +298,10 @@ int main(int argc, char **argv)
                lseek(fd, 0x20, SEEK_SET);
        else
                lseek(fd, 0x18, SEEK_SET);
-       if (BHDR)
-               *((u32 *) & buf[0x18]) = sum;
-       else
-               *((u32 *) & buf[0x18]) = sum0;
+       buf[0x18] = (BHDR ? sum : sum0) & 0xff;
+       buf[0x19] = ((BHDR ? sum : sum0) >> 8) & 0xff;
+       buf[0x1a] = ((BHDR ? sum : sum0) >> 16) & 0xff;
+       buf[0x1b] = ((BHDR ? sum : sum0) >> 24) & 0xff;
        write(fd, &buf[0x18], 0x4);
 
        sum = crc32(buf, l0);
@@ -305,17 +310,19 @@ int main(int argc, char **argv)
                lseek(fd, 0xC, SEEK_SET);
        else
                lseek(fd, 0x4, SEEK_SET);
-       *((u32 *) & buf[0x4]) = sum;
+       buf[0x4] = sum & 0xff;
+       buf[0x5] = (sum >> 8) & 0xff;
+       buf[0x6] = (sum >> 16) & 0xff;
+       buf[0x7] = (sum >> 24) & 0xff;
        write(fd, &buf[0x4], 0x4);
        if (EHDR) {
-               unsigned long sum2 = *((u32 *) & buf[-0x8]);
+               unsigned long sum2 = buf[-0x8] | ((u32)buf[-0x7] << 8) | ((u32)buf[-0x6] << 16) | ((u32)buf[-0x5] << 24);
                *((u32 *) & buf[-0x8]) = 0L;
                sum = crc32(buf - 0x4, len - 0x4);
-               sum = htonl(sum);
                printf("CRC32 sum2 - (%x, %x, %x)\n", sum, sum2,
                       len - 0x4);
                lseek(fd, 0, SEEK_SET);
-               *((u32 *) & buf[-0x8]) = sum;
+               *((u32 *) & buf[-0x8]) = htonl(sum);
                write(fd, &buf[-0x8], 0x4);
                buf -= 8;
        }