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