]> git.zerfleddert.de Git - proxmark3-svn/blame - client/fpga_compress.c
Compress the .data section as well (saves another 4KBytes and comes for free)
[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 fprintf(stderr, "zlib requested %d bytes\n", items*size);
49 return malloc(items*size);
e6153040 50}
e6153040 51
f3919878 52
53static void fpga_deflate_free(voidpf opaque, voidpf address)
e6153040 54{
f3919878 55 fprintf(stderr, "zlib frees memory\n");
56 return free(address);
57}
e6153040 58
f3919878 59
fb228974 60static 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
72int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile)
e6153040 73{
fb228974 74 uint8_t *fpga_config;
75 uint32_t i;
76 int ret;
77 uint8_t c;
f3919878 78 z_stream compressed_fpga_stream;
fb228974 79
80 fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE);
e6153040 81
fb228974 82 // read the input files interleaving into fpga_config[]
e6153040 83 i = 0;
fb228974 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]);
0fa01ec7 88 if (!feof(infile[j])) {
89 fpga_config[i++] = c;
90 } else if (num_infiles > 1) {
91 fpga_config[i++] = '\0';
92 }
fb228974 93 }
94 }
95
96 if (i > num_infiles * FPGA_CONFIG_SIZE) {
97 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);
98 for(uint16_t j = 0; j < num_infiles; j++) {
99 fclose(infile[j]);
100 }
e6153040 101 return -1;
102 }
fb228974 103 } while (!all_feof(infile, num_infiles));
e6153040 104
fb228974 105 fprintf(stderr, "Read a total of %ld bytes from %d files\n", i, num_infiles);
106
f3919878 107 // initialize zlib structures
108 compressed_fpga_stream.next_in = fpga_config;
109 compressed_fpga_stream.avail_in = i;
110 compressed_fpga_stream.zalloc = fpga_deflate_malloc;
111 compressed_fpga_stream.zfree = fpga_deflate_free;
e6153040 112
fb228974 113 ret = deflateInit2(&compressed_fpga_stream,
114 COMPRESS_LEVEL,
115 Z_DEFLATED,
116 COMPRESS_WINDOW_BITS,
117 COMPRESS_MEM_LEVEL,
118 COMPRESS_STRATEGY);
119
f3919878 120 // estimate the size of the compressed output
121 unsigned int outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in);
fb228974 122 fprintf(stderr, "Allocating %ld bytes for output file (estimated upper bound)\n", outsize_max);
f3919878 123 uint8_t *outbuf = malloc(outsize_max);
124 compressed_fpga_stream.next_out = outbuf;
125 compressed_fpga_stream.avail_out = outsize_max;
e6153040 126
fb228974 127
128 if (ret == Z_OK) {
129 ret = deflateTune(&compressed_fpga_stream,
130 COMPRESS_GOOD_LENGTH,
131 COMPRESS_MAX_LAZY,
132 COMPRESS_MAX_NICE_LENGTH,
133 COMPRESS_MAX_CHAIN);
134 }
135
f3919878 136 if (ret == Z_OK) {
137 ret = deflate(&compressed_fpga_stream, Z_FINISH);
e6153040 138 }
e6153040 139
f3919878 140 fprintf(stderr, "produced %d bytes of output\n", compressed_fpga_stream.total_out);
141
142 if (ret != Z_STREAM_END) {
143 fprintf(stderr, "Error in deflate(): %d %s\n", ret, compressed_fpga_stream.msg);
144 free(outbuf);
145 deflateEnd(&compressed_fpga_stream);
fb228974 146 for(uint16_t j = 0; j < num_infiles; j++) {
147 fclose(infile[j]);
148 }
f3919878 149 fclose(outfile);
fb228974 150 free(infile);
151 free(fpga_config);
f3919878 152 return -1;
153 }
e6153040 154
f3919878 155 for (i = 0; i < compressed_fpga_stream.total_out; i++) {
156 fputc(outbuf[i], outfile);
157 }
158
159 free(outbuf);
160 deflateEnd(&compressed_fpga_stream);
fb228974 161 for(uint16_t j = 0; j < num_infiles; j++) {
162 fclose(infile[j]);
163 }
e6153040 164 fclose(outfile);
fb228974 165 free(infile);
166 free(fpga_config);
167
e6153040 168 return 0;
f3919878 169
e6153040 170}
171
172
f3919878 173
e6153040 174int main(int argc, char **argv)
175{
fb228974 176 FILE **infiles;
177 FILE *outfile;
e6153040 178
fb228974 179 if (argc == 1 || argc == 2) {
e6153040 180 usage(argv[0]);
181 return -1;
fb228974 182 }
183
184 infiles = calloc(argc-2, sizeof(FILE*));
185
186 for (uint16_t i = 0; i < argc-2; i++) {
187 infiles[i] = fopen(argv[i+1], "rb");
188 if (infiles[i] == NULL) {
189 fprintf(stderr, "Error. Cannot open input file %s", argv[i+1]);
190 return -1;
e6153040 191 }
fb228974 192 }
193
194 outfile = fopen(argv[argc-1], "wb");
e6153040 195 if (outfile == NULL) {
fb228974 196 fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]);
e6153040 197 return -1;
198 }
199
fb228974 200 return zlib_compress(infiles, argc-2, outfile);
e6153040 201}
Impressum, Datenschutz