mkfwimage: Add image type definition for WA images
[openwrt/.git] / tools / firmware-utils / src / mkfwimage.c
index d8d5239cc55d1986459ce404c414f098500bf5ab..2b84d3db536eb2eba5ec1a9a6d08b7743db4bdd8 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <limits.h>
+#include <stdbool.h>
 #include "fw.h"
 
 typedef struct fw_layout_data {
-       char            name[PATH_MAX];
        u_int32_t       kern_start;
        u_int32_t       kern_entry;
        u_int32_t       firmware_max_length;
 } fw_layout_t;
 
-fw_layout_t fw_layout_data[] = {
+struct fw_info {
+       char                    name[PATH_MAX];
+       struct fw_layout_data   fw_layout;
+       bool                    sign;
+};
+
+struct fw_info fw_info[] = {
        {
-               .name           =       "XS2",
-               .kern_start     =       0xbfc30000,
-               .kern_entry     =       0x80041000,
-               .firmware_max_length=   0x00390000,
+               .name = "XS2",
+               .fw_layout = {
+                       .kern_start     =       0xbfc30000,
+                       .kern_entry     =       0x80041000,
+                       .firmware_max_length=   0x00390000,
+               },
+               .sign = false,
        },
        {
-               .name           =       "XS5",
-               .kern_start     =       0xbe030000,
-               .kern_entry     =       0x80041000,
-               .firmware_max_length=   0x00390000,
+               .name = "XS5",
+               .fw_layout = {
+                       .kern_start     =       0xbe030000,
+                       .kern_entry     =       0x80041000,
+                       .firmware_max_length=   0x00390000,
+               },
+               .sign = false,
        },
        {
-               .name           =       "RS",
-               .kern_start     =       0xbf030000,
-               .kern_entry     =       0x80060000,
-               .firmware_max_length=   0x00B00000,
+               .name = "RS",
+               .fw_layout = {
+                       .kern_start     =       0xbf030000,
+                       .kern_entry     =       0x80060000,
+                       .firmware_max_length=   0x00B00000,
+               },
+               .sign = false,
        },
        {
-               .name           =       "RSPRO",
-               .kern_start     =       0xbf030000,
-               .kern_entry     =       0x80060000,
-               .firmware_max_length=   0x00F00000,
+               .name = "RSPRO",
+               .fw_layout = {
+                       .kern_start     =       0xbf030000,
+                       .kern_entry     =       0x80060000,
+                       .firmware_max_length=   0x00F00000,
+               },
+               .sign = false,
        },
        {
-               .name           =       "LS-SR71",
-               .kern_start     =       0xbf030000,
-               .kern_entry     =       0x80060000,
-               .firmware_max_length=   0x00640000,
+               .name = "LS-SR71",
+               .fw_layout = {
+                       .kern_start     =       0xbf030000,
+                       .kern_entry     =       0x80060000,
+                       .firmware_max_length=   0x00640000,
+               },
+               .sign = false,
        },
        {
-               .name           =       "XS2-8",
-               .kern_start     =       0xa8030000,
-               .kern_entry     =       0x80041000,
-               .firmware_max_length=   0x006C0000,
+               .name = "XS2-8",
+               .fw_layout = {
+                       .kern_start     =       0xa8030000,
+                       .kern_entry     =       0x80041000,
+                       .firmware_max_length=   0x006C0000,
+               },
+               .sign = false,
+
        },
        {
-               .name           =       "XM",
-               .kern_start     =       0x9f050000,
-               .kern_entry     =       0x80002000,
-               .firmware_max_length=   0x00760000,
+               .name = "XM",
+               .fw_layout = {
+                       .kern_start     =       0x9f050000,
+                       .kern_entry     =       0x80002000,
+                       .firmware_max_length=   0x00760000,
+               },
+               .sign = false,
        },
        {
-               .name           =       "UBDEV01",
-               .kern_start     =       0x9f050000,
-               .kern_entry     =       0x80002000,
-               .firmware_max_length=   0x006A0000,
+               .name = "UBDEV01",
+               .fw_layout = {
+                       .kern_start     =       0x9f050000,
+                       .kern_entry     =       0x80002000,
+                       .firmware_max_length=   0x006A0000,
+               },
+               .sign = false,
        },
-       {       .name           =       "",
+       {
+               .name = "WA",
+               .fw_layout = {
+                       .kern_start     =       0x9f050000,
+                       .kern_entry     =       0x80002000,
+                       .firmware_max_length=   0x00F60000,
+               },
+               .sign = true,
+       },
+       {
+               .name = "",
        },
 };
 
@@ -116,8 +157,20 @@ typedef struct image_info {
        char outputfile[PATH_MAX];
        u_int32_t       part_count;
        part_data_t parts[MAX_SECTIONS];
+       struct fw_info* fwinfo;
 } image_info_t;
 
+static struct fw_info* get_fwinfo(char* board_name) {
+       struct fw_info *fwinfo = fw_info;
+       while(strlen(fwinfo->name)) {
+               if(strcmp(fwinfo->name, board_name) == 0) {
+                       return fwinfo;
+               }
+               fwinfo++;
+       }
+       return NULL;
+}
+
 static void write_header(void* mem, const char *magic, const char* version)
 {
        header_t* header = mem;
@@ -142,6 +195,17 @@ static void write_signature(void* mem, u_int32_t sig_offset)
        sign->pad = 0L;
 }
 
+static void write_signature_rsa(void* mem, u_int32_t sig_offset)
+{
+       /* write signature */
+       signature_rsa_t* sign = (signature_rsa_t*)(mem + sig_offset);
+       memset(sign, 0, sizeof(signature_rsa_t));
+
+       memcpy(sign->magic, MAGIC_ENDS, MAGIC_LENGTH);
+//     sign->crc = htonl(crc32(0L,(unsigned char *)mem, sig_offset));
+       sign->pad = 0L;
+}
+
 static int write_part(void* mem, part_data_t* d)
 {
        char* addr;
@@ -237,17 +301,9 @@ static int create_image_layout(const char* kernelfile, const char* rootfsfile, c
        part_data_t* kernel = &im->parts[0];
        part_data_t* rootfs = &im->parts[1];
 
-       fw_layout_t* p;
+       fw_layout_t* p = &im->fwinfo->fw_layout;
 
-       p = &fw_layout_data[0];
-       while (*p->name && (strcmp(p->name, board_name) != 0))
-               p++;
-       if (!*p->name) {
-               printf("BUG! Unable to find default fw layout!\n");
-               exit(-1);
-       }
-
-       printf("board = %s\n", p->name);
+       printf("board = %s\n", im->fwinfo->name);
        strcpy(kernel->partition_name, "kernel");
        kernel->partition_index = 1;
        kernel->partition_baseaddr = p->kern_start;
@@ -330,7 +386,12 @@ static int build_image(image_info_t* im)
        int i;
 
        // build in-memory buffer
-       mem_size = sizeof(header_t) + sizeof(signature_t);
+       mem_size = sizeof(header_t);
+       if(im->fwinfo->sign) {
+               mem_size += sizeof(signature_rsa_t);
+       } else {
+               mem_size += sizeof(signature_t);
+       }
        for (i = 0; i < im->part_count; ++i)
        {
                part_data_t* d = &im->parts[i];
@@ -359,7 +420,11 @@ static int build_image(image_info_t* im)
                ptr += sizeof(part_t) + d->stats.st_size + sizeof(part_crc_t);
        }
        // write signature
-       write_signature(mem, mem_size - sizeof(signature_t));
+       if(im->fwinfo->sign) {
+               write_signature_rsa(mem, mem_size - sizeof(signature_rsa_t));
+       } else {
+               write_signature(mem, mem_size - sizeof(signature_t));
+       }
 
        // write in-memory buffer into file
        if ((f = fopen(im->outputfile, "w")) == NULL)
@@ -388,6 +453,7 @@ int main(int argc, char* argv[])
        char board_name[PATH_MAX];
        int o, rc;
        image_info_t im;
+       struct fw_info *fwinfo;
 
        memset(&im, 0, sizeof(im));
        memset(kernelfile, 0, sizeof(kernelfile));
@@ -447,6 +513,14 @@ int main(int argc, char* argv[])
                return -2;
        }
 
+       if ((fwinfo = get_fwinfo(board_name)) == NULL) {
+               ERROR("Invalid baord name '%s'\n", board_name);
+               usage(argv[0]);
+               return -2;
+       }
+
+       im.fwinfo = fwinfo;
+
        if ((rc = create_image_layout(kernelfile, rootfsfile, board_name, &im)) != 0)
        {
                ERROR("Failed creating firmware layout description - error code: %d\n", rc);