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
5 //-----------------------------------------------------------------------------
6 // Flasher frontend tool
7 //-----------------------------------------------------------------------------
13 #include "proxmark3.h"
18 #define MAX(a,b) ((a)>(b)?(a):(b))
20 struct huffman_record
{
25 struct huffman_record
*left
;
26 struct huffman_record
*right
;
27 struct huffman_record
*next
;
30 typedef struct huffman_record huffman_record_t
;
32 #define FPGA_CONFIG_SIZE 42175
33 static uint8_t fpga_config
[FPGA_CONFIG_SIZE
];
34 static huffman_record_t leaf_nodes
[256];
35 static uint8_t start_code
[256];
37 static void usage(char *argv0
)
39 fprintf(stderr
, "Usage: %s [-d] <infile> <outfile>\n\n", argv0
);
40 fprintf(stderr
, "\t-d\tdecompress\n\n");
44 void add_to_heap(huffman_record_t
**heap
, huffman_record_t
*new_record
)
46 huffman_record_t
*succ
= *heap
;
47 huffman_record_t
*pred
= NULL
;
49 // fprintf(stderr, "Adding symbol %d, count %d\n", new_record->symbol, new_record->count);
51 while (succ
!= NULL
&& new_record
->count
> succ
->count
) {
57 new_record
->next
= succ
;
58 if (pred
== NULL
) { // first record in heap
61 pred
->next
= new_record
;
66 uint16_t set_codesize(huffman_record_t
*tree_ptr
, uint8_t depth
)
68 uint16_t max_size
= depth
;
69 tree_ptr
->code_size
= depth
;
70 if (tree_ptr
->left
!= NULL
) {
71 max_size
= MAX(set_codesize(tree_ptr
->left
, depth
+1), max_size
);
73 if (tree_ptr
->right
!= NULL
) {
74 max_size
= MAX(set_codesize(tree_ptr
->right
, depth
+1), max_size
);
79 int huffman_encode(FILE *infile
, FILE *outfile
)
84 for (i
= 0; i
< 256; i
++) {
85 leaf_nodes
[i
].count
= 0;
86 leaf_nodes
[i
].symbol
= i
;
87 leaf_nodes
[i
].left
= NULL
;
88 leaf_nodes
[i
].right
= NULL
;
89 leaf_nodes
[i
].next
= NULL
;
92 // read the input file into fpga_config[] and count occurrences of each symbol:
94 while(!feof(infile
)) {
98 leaf_nodes
[c
].count
++;
99 if (i
> FPGA_CONFIG_SIZE
+1) {
100 fprintf(stderr
, "Input file too big (> %d bytes). This is probably not a PM3 FPGA config file.", FPGA_CONFIG_SIZE
);
107 fprintf(stderr
, "\nStatistics: (symbol: count)\n");
108 for (i
= 0; i
< 256; i
++) {
109 fprintf(stderr
, "%3d: %5d\n", i
, leaf_nodes
[i
].count
);
112 // build the Huffman tree:
113 huffman_record_t
*heap_ptr
= NULL
;
115 for (i
= 0; i
< 256; i
++) {
116 add_to_heap(&heap_ptr
, &leaf_nodes
[i
]);
119 fprintf(stderr
, "\nSorted statistics: (symbol: count)\n");
120 for (huffman_record_t
*p
= heap_ptr
; p
!= NULL
; p
= p
->next
) {
121 fprintf(stderr
, "%3d: %5d\n", p
->symbol
, p
->count
);
124 for (i
= 0; i
< 255; i
++) {
125 // remove and combine the first two nodes
126 huffman_record_t
*p1
, *p2
;
130 huffman_record_t
*new_node
= malloc(sizeof(huffman_record_t
));
132 new_node
->right
= p2
;
133 new_node
->count
= p1
->count
+ p2
->count
;
134 add_to_heap(&heap_ptr
, new_node
);
137 uint16_t max_codesize
= set_codesize(heap_ptr
, 0);
139 fprintf(stderr
, "\nStatistics: (symbol: count, codesize)\n");
140 uint32_t compressed_size
= 0;
141 for (i
= 0; i
< 256; i
++) {
142 fprintf(stderr
, "%3d: %5d, %d\n", leaf_nodes
[i
].symbol
, leaf_nodes
[i
].count
, leaf_nodes
[i
].code_size
);
143 compressed_size
+= leaf_nodes
[i
].count
* leaf_nodes
[i
].code_size
;
145 fprintf(stderr
, "Compressed size = %ld (%f% of original size)", (compressed_size
+7)/8, (float)(compressed_size
)/(FPGA_CONFIG_SIZE
* 8) * 100);
146 fprintf(stderr
, "Max Codesize = %d bits", max_codesize
);
149 for (i
= max_codesize
; i
> 0; i
--) {
150 code
= (code
+ 1) >> 1;
151 start_code
[i
] = code
;
152 for (uint16_t j
= 0; j
< 256; j
++) {
153 if (leaf_nodes
[j
].code_size
== i
) {
154 leaf_nodes
[j
].code
= code
;
161 fprintf(stderr
, "\nStatistics: (symbol: count, codesize, code)\n");
162 for (i
= 0; i
< 256; i
++) {
163 fprintf(stderr
, "%3d: %5d, %d, %02x\n", leaf_nodes
[i
].symbol
, leaf_nodes
[i
].count
, leaf_nodes
[i
].code_size
, leaf_nodes
[i
].code
);
172 int huffman_decode(FILE *infile
, FILE *outfile
)
178 int main(int argc
, char **argv
)
190 if (!strcmp(argv
[1], "-d")) {
192 infilename
= argv
[2];
193 outfilename
= argv
[3];
199 infilename
= argv
[1];
200 outfilename
= argv
[2];
203 FILE *infile
= fopen(infilename
, "rb");
204 if (infile
== NULL
) {
205 fprintf(stderr
, "Error. Cannot open input file %s", infilename
);
209 FILE *outfile
= fopen(outfilename
, "wb");
210 if (outfile
== NULL
) {
211 fprintf(stderr
, "Error. Cannot open output file %s", outfilename
);
217 return huffman_decode(infile
, outfile
);
219 return huffman_encode(infile
, outfile
);