]> git.zerfleddert.de Git - proxmark3-svn/blob - client/fpga_compress.c
d4376ccc96a1cdc50f92bcc21e1ba0f258639005
[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 // Flasher frontend tool
7 //-----------------------------------------------------------------------------
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdint.h>
13 #include <stdbool.h>
14 #include "zlib.h"
15
16 #define MAX(a,b) ((a)>(b)?(a):(b))
17
18 // zlib configuration
19 #define COMPRESS_LEVEL 9 // use best possible compression
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
38
39 static void usage(char *argv0)
40 {
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");
43 }
44
45
46 static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size)
47 {
48 fprintf(stderr, "zlib requested %d bytes\n", items*size);
49 return malloc(items*size);
50 }
51
52
53 static void fpga_deflate_free(voidpf opaque, voidpf address)
54 {
55 fprintf(stderr, "zlib frees memory\n");
56 return free(address);
57 }
58
59
60 static bool all_feof(FILE *infile[], uint8_t num_infiles)
61 {
62 for (uint16_t i = 0; i < num_infiles; i++) {
63 if (!feof(infile[i])) {
64 return false;
65 }
66 }
67
68 return true;
69 }
70
71
72 int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile)
73 {
74 uint8_t *fpga_config;
75 uint32_t i;
76 int ret;
77 uint8_t c;
78 z_stream compressed_fpga_stream;
79
80 fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE);
81
82 // read the input files interleaving into fpga_config[]
83 i = 0;
84 do {
85 for(uint16_t j = 0; j < num_infiles; j++) {
86 for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) {
87 c = fgetc(infile[j]);
88 if (!feof(infile[j])) fpga_config[i++] = c; else fpga_config[i++] = '\0';
89 }
90 }
91
92 if (i > num_infiles * FPGA_CONFIG_SIZE) {
93 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);
94 for(uint16_t j = 0; j < num_infiles; j++) {
95 fclose(infile[j]);
96 }
97 return -1;
98 }
99 } while (!all_feof(infile, num_infiles));
100
101 fprintf(stderr, "Read a total of %ld bytes from %d files\n", i, num_infiles);
102
103 // initialize zlib structures
104 compressed_fpga_stream.next_in = fpga_config;
105 compressed_fpga_stream.avail_in = i;
106 compressed_fpga_stream.zalloc = fpga_deflate_malloc;
107 compressed_fpga_stream.zfree = fpga_deflate_free;
108
109 ret = deflateInit2(&compressed_fpga_stream,
110 COMPRESS_LEVEL,
111 Z_DEFLATED,
112 COMPRESS_WINDOW_BITS,
113 COMPRESS_MEM_LEVEL,
114 COMPRESS_STRATEGY);
115
116 // estimate the size of the compressed output
117 unsigned int outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in);
118 fprintf(stderr, "Allocating %ld bytes for output file (estimated upper bound)\n", outsize_max);
119 uint8_t *outbuf = malloc(outsize_max);
120 compressed_fpga_stream.next_out = outbuf;
121 compressed_fpga_stream.avail_out = outsize_max;
122
123
124 if (ret == Z_OK) {
125 ret = deflateTune(&compressed_fpga_stream,
126 COMPRESS_GOOD_LENGTH,
127 COMPRESS_MAX_LAZY,
128 COMPRESS_MAX_NICE_LENGTH,
129 COMPRESS_MAX_CHAIN);
130 }
131
132 if (ret == Z_OK) {
133 ret = deflate(&compressed_fpga_stream, Z_FINISH);
134 }
135
136 fprintf(stderr, "produced %d bytes of output\n", compressed_fpga_stream.total_out);
137
138 if (ret != Z_STREAM_END) {
139 fprintf(stderr, "Error in deflate(): %d %s\n", ret, compressed_fpga_stream.msg);
140 free(outbuf);
141 deflateEnd(&compressed_fpga_stream);
142 for(uint16_t j = 0; j < num_infiles; j++) {
143 fclose(infile[j]);
144 }
145 fclose(outfile);
146 free(infile);
147 free(fpga_config);
148 return -1;
149 }
150
151 for (i = 0; i < compressed_fpga_stream.total_out; i++) {
152 fputc(outbuf[i], outfile);
153 }
154
155 free(outbuf);
156 deflateEnd(&compressed_fpga_stream);
157 for(uint16_t j = 0; j < num_infiles; j++) {
158 fclose(infile[j]);
159 }
160 fclose(outfile);
161 free(infile);
162 free(fpga_config);
163
164 return 0;
165
166 }
167
168
169
170 int main(int argc, char **argv)
171 {
172 FILE **infiles;
173 FILE *outfile;
174
175 if (argc == 1 || argc == 2) {
176 usage(argv[0]);
177 return -1;
178 }
179
180 infiles = calloc(argc-2, sizeof(FILE*));
181
182 for (uint16_t i = 0; i < argc-2; i++) {
183 infiles[i] = fopen(argv[i+1], "rb");
184 if (infiles[i] == NULL) {
185 fprintf(stderr, "Error. Cannot open input file %s", argv[i+1]);
186 return -1;
187 }
188 }
189
190 outfile = fopen(argv[argc-1], "wb");
191 if (outfile == NULL) {
192 fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]);
193 return -1;
194 }
195
196 return zlib_compress(infiles, argc-2, outfile);
197 }
Impressum, Datenschutz