]> git.zerfleddert.de Git - proxmark3-svn/blob - client/fpga_compress.c
c13026941362b96603ac1cfc7d5f2da609027699
[proxmark3-svn] / client / fpga_compress.c
1 //-----------------------------------------------------------------------------
2 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
3 // at your option, any later version. See the LICENSE.txt file for the text of
4 // the license.
5 //-----------------------------------------------------------------------------
6 // Compression tool for FPGA config files. Compress several *.bit files at
7 // compile time. Decompression is done at run time (see fpgaloader.c).
8 // This uses the zlib library tuned to this specific case. The small file sizes
9 // allow to use "insane" parameters for optimum compression ratio.
10 //-----------------------------------------------------------------------------
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdint.h>
16 #include <stdbool.h>
17 #include <inttypes.h>
18 #include "zlib.h"
19
20 #define MAX(a,b) ((a)>(b)?(a):(b))
21
22 // zlib configuration
23 #define COMPRESS_LEVEL 9 // use best possible compression
24 #define COMPRESS_WINDOW_BITS 15 // default = max = 15 for a window of 2^15 = 32KBytes
25 #define COMPRESS_MEM_LEVEL 9 // determines the amount of memory allocated during compression. Default = 8.
26 /* COMPRESS_STRATEGY can be
27 Z_DEFAULT_STRATEGY (the default),
28 Z_FILTERED (more huffmann, less string matching),
29 Z_HUFFMAN_ONLY (huffman only, no string matching)
30 Z_RLE (distances limited to one)
31 Z_FIXED (prevents the use of dynamic Huffman codes)
32 */
33 #define COMPRESS_STRATEGY Z_DEFAULT_STRATEGY
34 // zlib tuning parameters:
35 #define COMPRESS_GOOD_LENGTH 258
36 #define COMPRESS_MAX_LAZY 258
37 #define COMPRESS_MAX_NICE_LENGTH 258
38 #define COMPRESS_MAX_CHAIN 8192
39
40 #define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression)
41 #define FPGA_CONFIG_SIZE 42336 // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE
42
43 static void usage(void)
44 {
45 fprintf(stderr, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n");
46 fprintf(stderr, " Combine n FPGA bitstream files and compress them into one.\n\n");
47 fprintf(stderr, " fpga_compress -d <infile> <outfile>");
48 fprintf(stderr, " Decompress <infile>. Write result to <outfile>");
49 }
50
51
52 static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size)
53 {
54 return malloc(items*size);
55 }
56
57
58 static void fpga_deflate_free(voidpf opaque, voidpf address)
59 {
60 return free(address);
61 }
62
63
64 static bool all_feof(FILE *infile[], uint8_t num_infiles)
65 {
66 for (uint16_t i = 0; i < num_infiles; i++) {
67 if (!feof(infile[i])) {
68 return false;
69 }
70 }
71
72 return true;
73 }
74
75
76 int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile)
77 {
78 uint8_t *fpga_config;
79 uint32_t i;
80 int ret;
81 int c;
82 z_stream compressed_fpga_stream;
83
84 fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE);
85
86 // read the input files. Interleave them into fpga_config[]
87 i = 0;
88 do {
89
90 if (i >= num_infiles * FPGA_CONFIG_SIZE) {
91 fprintf(stderr, "Input files too big (total > %d bytes). These are probably not PM3 FPGA config files.\n", num_infiles*FPGA_CONFIG_SIZE);
92 for(uint16_t j = 0; j < num_infiles; j++) {
93 fclose(infile[j]);
94 }
95 free(fpga_config);
96 return(EXIT_FAILURE);
97 }
98
99 for(uint16_t j = 0; j < num_infiles; j++) {
100 for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) {
101 c = fgetc(infile[j]);
102 if (!feof(infile[j])) {
103 fpga_config[i++] = c &0xFF;
104 } else if (num_infiles > 1) {
105 fpga_config[i++] = '\0';
106 }
107 }
108 }
109
110 } while (!all_feof(infile, num_infiles));
111
112 // initialize zlib structures
113 compressed_fpga_stream.next_in = fpga_config;
114 compressed_fpga_stream.avail_in = i;
115 compressed_fpga_stream.zalloc = fpga_deflate_malloc;
116 compressed_fpga_stream.zfree = fpga_deflate_free;
117 compressed_fpga_stream.opaque = Z_NULL;
118
119 ret = deflateInit2(&compressed_fpga_stream,
120 COMPRESS_LEVEL,
121 Z_DEFLATED,
122 COMPRESS_WINDOW_BITS,
123 COMPRESS_MEM_LEVEL,
124 COMPRESS_STRATEGY);
125
126 // estimate the size of the compressed output
127 unsigned int outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in);
128 uint8_t *outbuf = malloc(outsize_max);
129 compressed_fpga_stream.next_out = outbuf;
130 compressed_fpga_stream.avail_out = outsize_max;
131
132 if (ret == Z_OK) {
133 ret = deflateTune(&compressed_fpga_stream,
134 COMPRESS_GOOD_LENGTH,
135 COMPRESS_MAX_LAZY,
136 COMPRESS_MAX_NICE_LENGTH,
137 COMPRESS_MAX_CHAIN);
138 }
139
140 if (ret == Z_OK) {
141 ret = deflate(&compressed_fpga_stream, Z_FINISH);
142 }
143
144 fprintf(stderr, "compressed %u input bytes to %" PRIu32 " output bytes\n", i, compressed_fpga_stream.total_out);
145
146 if (ret != Z_STREAM_END) {
147 fprintf(stderr, "Error in deflate(): %d %s\n", ret, compressed_fpga_stream.msg);
148 free(outbuf);
149 deflateEnd(&compressed_fpga_stream);
150 for(uint16_t j = 0; j < num_infiles; j++) {
151 fclose(infile[j]);
152 }
153 fclose(outfile);
154 free(infile);
155 free(fpga_config);
156 return(EXIT_FAILURE);
157 }
158
159 for (i = 0; i < compressed_fpga_stream.total_out; i++) {
160 fputc(outbuf[i], outfile);
161 }
162
163 free(outbuf);
164 deflateEnd(&compressed_fpga_stream);
165 for(uint16_t j = 0; j < num_infiles; j++) {
166 fclose(infile[j]);
167 }
168 fclose(outfile);
169 free(infile);
170 free(fpga_config);
171
172 return(EXIT_SUCCESS);
173
174 }
175
176
177 int zlib_decompress(FILE *infile, FILE *outfile)
178 {
179 #define DECOMPRESS_BUF_SIZE 1024
180 uint8_t outbuf[DECOMPRESS_BUF_SIZE];
181 uint8_t inbuf[DECOMPRESS_BUF_SIZE];
182 int ret;
183
184 z_stream compressed_fpga_stream;
185
186 // initialize zlib structures
187 compressed_fpga_stream.next_in = inbuf;
188 compressed_fpga_stream.avail_in = 0;
189 compressed_fpga_stream.next_out = outbuf;
190 compressed_fpga_stream.avail_out = DECOMPRESS_BUF_SIZE;
191 compressed_fpga_stream.zalloc = fpga_deflate_malloc;
192 compressed_fpga_stream.zfree = fpga_deflate_free;
193 compressed_fpga_stream.opaque = Z_NULL;
194
195 ret = inflateInit2(&compressed_fpga_stream, 0);
196
197 do {
198 if (compressed_fpga_stream.avail_in == 0) {
199 compressed_fpga_stream.next_in = inbuf;
200 uint16_t i = 0;
201 do {
202 int c = fgetc(infile);
203 if (!feof(infile)) {
204 inbuf[i++] = c;
205 compressed_fpga_stream.avail_in++;
206 } else {
207 break;
208 }
209 } while (i < DECOMPRESS_BUF_SIZE);
210 }
211
212 ret = inflate(&compressed_fpga_stream, Z_SYNC_FLUSH);
213
214 if (ret != Z_OK && ret != Z_STREAM_END) {
215 break;
216 }
217
218 if (compressed_fpga_stream.avail_out == 0) {
219 for (uint16_t i = 0; i < DECOMPRESS_BUF_SIZE; i++) {
220 fputc(outbuf[i], outfile);
221 }
222 compressed_fpga_stream.avail_out = DECOMPRESS_BUF_SIZE;
223 compressed_fpga_stream.next_out = outbuf;
224 }
225 } while (ret == Z_OK);
226
227 if (ret == Z_STREAM_END) { // reached end of input
228 uint16_t i = 0;
229 while (compressed_fpga_stream.avail_out < DECOMPRESS_BUF_SIZE) {
230 fputc(outbuf[i++], outfile);
231 compressed_fpga_stream.avail_out++;
232 }
233 fclose(outfile);
234 fclose(infile);
235 return(EXIT_SUCCESS);
236 } else {
237 fprintf(stderr, "Error. Inflate() returned error %d, %s", ret, compressed_fpga_stream.msg);
238 fclose(outfile);
239 fclose(infile);
240 return(EXIT_FAILURE);
241 }
242
243 }
244
245
246 int main(int argc, char **argv)
247 {
248 FILE **infiles;
249 FILE *outfile;
250
251 if (argc == 1 || argc == 2) {
252 usage();
253 return(EXIT_FAILURE);
254 }
255
256 if (!strcmp(argv[1], "-d")) { // Decompress
257 infiles = calloc(1, sizeof(FILE*));
258 if (argc != 4) {
259 usage();
260 return(EXIT_FAILURE);
261 }
262 infiles[0] = fopen(argv[2], "rb");
263 if (infiles[0] == NULL) {
264 fprintf(stderr, "Error. Cannot open input file %s", argv[2]);
265 return(EXIT_FAILURE);
266 }
267 outfile = fopen(argv[3], "wb");
268 if (outfile == NULL) {
269 fprintf(stderr, "Error. Cannot open output file %s", argv[3]);
270 return(EXIT_FAILURE);
271 }
272 return zlib_decompress(infiles[0], outfile);
273
274 } else { // Compress
275
276 infiles = calloc(argc-2, sizeof(FILE*));
277 for (uint16_t i = 0; i < argc-2; i++) {
278 infiles[i] = fopen(argv[i+1], "rb");
279 if (infiles[i] == NULL) {
280 fprintf(stderr, "Error. Cannot open input file %s", argv[i+1]);
281 return(EXIT_FAILURE);
282 }
283 }
284 outfile = fopen(argv[argc-1], "wb");
285 if (outfile == NULL) {
286 fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]);
287 return(EXIT_FAILURE);
288 }
289 return zlib_compress(infiles, argc-2, outfile);
290 }
291 }
Impressum, Datenschutz