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