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