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