ath79: add support for TP-Link Archer C6 v2
[oweals/openwrt.git] / tools / firmware-utils / src / zyimage.c
1 /*
2  * Copyright (C) 2014 Soul Trace <S-trace@list.ru>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 as published
6  * by the Free Software Foundation.
7  *
8  */
9
10 #define _POSIX_SOURCE
11 #define _POSIX_C_SOURCE 199309L /* getopt */
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 #define szbuf 32768
19
20 u_int32_t crc_tab[256];
21
22 u_int32_t chksum_crc32 (FILE *f)
23 {
24   register unsigned long crc;
25   unsigned long i, j;
26   char *buffer = malloc(szbuf);
27   char *buf;
28
29   crc = 0xFFFFFFFF;
30   while (!feof(f))
31   {
32     j = fread(buffer, 1, szbuf, f);
33     buf = buffer;
34     for (i = 0; i < j; i++)
35       crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *buf++) & 0xFF];
36   }
37   free(buffer);
38   return crc;
39 }
40
41 void chksum_crc32gentab ()
42 {
43   unsigned long crc, poly;
44   int i, j;
45
46   poly = 0xEDB88320L;
47   for (i = 0; i < 256; i++)
48   {
49     crc = i;
50     for (j = 8; j > 0; j--)
51     {
52       if (crc & 1)
53         crc = (crc >> 1) ^ poly;
54       else
55         crc >>= 1;
56     }
57     crc_tab[i] = crc;
58   }
59 }
60
61 void usage(char *progname)
62 {
63   printf("Usage: %s [ -v Version ] [ -d Device_ID ] <input file>\n", progname);
64   exit(1);
65 }
66
67 int main(int argc, char *argv[]) {
68   struct signature
69   {
70     const char magic[4];
71     unsigned int device_id;
72     char firmware_version[48];
73     unsigned int crc32;
74   }
75   sign =
76   {
77     { 'Z', 'N', 'B', 'G' },
78     1,
79     { "V.1.0.0(1.0.0)" },
80     0
81   };
82   FILE *f;
83   struct signature oldsign;
84   char *filename;
85   static const char *optString;
86   int opt;
87
88   if (argc < 1)
89     usage(argv[0]);
90
91   optString = "v:d:h";
92   opt = getopt( argc, argv, optString );
93   while( opt != -1 ) {
94     switch( opt ) {
95       case 'v':
96         if (optarg == NULL)
97           usage(argv[0]);
98         strncpy(sign.firmware_version, optarg, sizeof(sign.firmware_version)-1);
99        sign.firmware_version[sizeof(sign.firmware_version)-1]='\0'; /* Make sure that string is terminated correctly */
100         break;
101
102       case 'd':
103         sign.device_id = atoi(optarg);
104         if (sign.device_id == 0)
105           sign.device_id = (int)strtol(optarg, NULL, 16);
106         break;
107
108       case '?':
109       case 'h':
110         usage(argv[0]);
111         break;
112
113       default:
114         break;
115     }
116
117     opt = getopt( argc, argv, optString );
118   }
119
120   chksum_crc32gentab();
121
122   filename=argv[optind];
123   if (access(filename, W_OK) || access(filename, R_OK))
124   {
125     printf("Not open input file %s\n", filename);
126     exit(1);
127   }
128   f = fopen(argv[optind], "r+");
129   if (f != NULL)
130   {
131     fseek(f, sizeof(sign)*-1, SEEK_END);
132     fread(&oldsign, sizeof(oldsign), 1, f);
133
134     if (strncmp(oldsign.magic,"ZNBG", sizeof(oldsign.magic)) == 0 )
135     {
136       printf("Image is already signed as:\nDevice ID: 0x%08x\nFirmware version: %s\nImage CRC32: 0x%x\n", oldsign.device_id, oldsign.firmware_version, oldsign.crc32);
137       exit(0);
138     }
139
140     fseek(f, 0, SEEK_SET);
141     sign.crc32 = chksum_crc32(f);
142     fwrite(&sign, sizeof(sign), 1, f);
143     fclose(f);
144
145     printf("Image signed as:\nDevice ID: 0x%08x\nFirmware version: %s\nImage CRC32: 0x%x\n", sign.device_id, sign.firmware_version, sign.crc32);
146   }
147   return 0;
148 }