blob: 8be11e9a924c5d0560d4e4d759ba30d919a9e995 [file] [log] [blame]
Damien Zammit06853222016-11-16 21:06:54 +11001/*
Denis 'GNUtoo' Carikli780e9312018-01-10 14:35:55 +01002 * bincfg - Compiler/Decompiler for data blobs with specs
Damien Zammit06853222016-11-16 21:06:54 +11003 * Copyright (C) 2017 Damien Zammit <damien@zamaudio.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16%{
17#include <stdio.h>
18#include <inttypes.h>
19#include <stdlib.h>
20#include <string.h>
Denis 'GNUtoo' Cariklifa0bdfc2018-01-12 04:04:30 +010021#include "bincfg.h"
Damien Zammit06853222016-11-16 21:06:54 +110022//#define YYDEBUG 1
Damien Zammit06853222016-11-16 21:06:54 +110023
Martin Roth63381892017-04-09 13:30:17 -060024static void check_pointer (void *ptr)
25{
26 if (ptr == NULL) {
27 printf("Error: Out of memory\n");
28 exit(1);
29 }
30}
31
32static unsigned char* value_to_bits (unsigned int v, unsigned int w)
Damien Zammit06853222016-11-16 21:06:54 +110033{
34 unsigned int i;
35 unsigned char* bitarr;
36
37 if (w > MAX_WIDTH) w = MAX_WIDTH;
38 bitarr = (unsigned char *) malloc (w * sizeof (unsigned char));
Martin Roth63381892017-04-09 13:30:17 -060039 check_pointer(bitarr);
Damien Zammit06853222016-11-16 21:06:54 +110040 memset (bitarr, 0, w);
41
42 for (i = 0; i < w; i++) {
43 bitarr[i] = VALID_BIT | ((v & (1 << i)) >> i);
44 }
45 return bitarr;
46}
47
48/* Store each bit of a bitfield in a new byte sequentially 0x80 or 0x81 */
Martin Roth63381892017-04-09 13:30:17 -060049static void append_field_to_blob (unsigned char b[], unsigned int w)
Damien Zammit06853222016-11-16 21:06:54 +110050{
51 unsigned int i, j;
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +010052 binary->blb = (unsigned char *) realloc (binary->blb,
53 binary->bloblen + w);
Martin Roth63381892017-04-09 13:30:17 -060054 check_pointer(binary->blb);
Damien Zammit06853222016-11-16 21:06:54 +110055 for (j = 0, i = binary->bloblen; i < binary->bloblen + w; i++, j++) {
56 binary->blb[i] = VALID_BIT | (b[j] & 1);
57 //fprintf (stderr, "blob[%d] = %d\n", i, binary->blb[i] & 1);
58 }
59 binary->bloblen += w;
60}
61
Martin Roth63381892017-04-09 13:30:17 -060062static void set_bitfield(char *name, unsigned int value)
Damien Zammit06853222016-11-16 21:06:54 +110063{
64 unsigned long long i;
65 struct field *bf = getsym (name);
66 if (bf) {
67 bf->value = value & 0xffffffff;
68 i = (1 << bf->width) - 1;
69 if (bf->width > 8 * sizeof (unsigned int)) {
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +010070 fprintf(stderr,
71 "Overflow in bitfield, truncating bits to"
72 " fit\n");
Damien Zammit06853222016-11-16 21:06:54 +110073 bf->value = value & i;
74 }
75 //fprintf(stderr, "Setting `%s` = %d\n", bf->name, bf->value);
76 } else {
77 fprintf(stderr, "Can't find bitfield `%s` in spec\n", name);
78 }
79}
80
Martin Roth63381892017-04-09 13:30:17 -060081static void set_bitfield_array(char *name, unsigned int n, unsigned int value)
Damien Zammit06853222016-11-16 21:06:54 +110082{
83 unsigned int i;
Martin Roth63381892017-04-09 13:30:17 -060084 unsigned long len = strlen (name);
Damien Zammit06853222016-11-16 21:06:54 +110085 char *namen = (char *) malloc ((len + 9) * sizeof (char));
Martin Roth63381892017-04-09 13:30:17 -060086 check_pointer(namen);
Damien Zammit06853222016-11-16 21:06:54 +110087 for (i = 0; i < n; i++) {
88 snprintf (namen, len + 8, "%s%x", name, i);
89 set_bitfield (namen, value);
90 }
91 free(namen);
92}
93
Martin Roth63381892017-04-09 13:30:17 -060094static void create_new_bitfield(char *name, unsigned int width)
Damien Zammit06853222016-11-16 21:06:54 +110095{
96 struct field *bf;
97
98 if (!(bf = putsym (name, width))) return;
99 //fprintf(stderr, "Added bitfield `%s` : %d\n", bf->name, width);
100}
101
Martin Roth63381892017-04-09 13:30:17 -0600102static void create_new_bitfields(char *name, unsigned int n, unsigned int width)
Damien Zammit06853222016-11-16 21:06:54 +1100103{
104 unsigned int i;
Martin Roth63381892017-04-09 13:30:17 -0600105 unsigned long len = strlen (name);
Damien Zammit06853222016-11-16 21:06:54 +1100106 char *namen = (char *) malloc ((len + 9) * sizeof (char));
Martin Roth63381892017-04-09 13:30:17 -0600107 check_pointer(namen);
Damien Zammit06853222016-11-16 21:06:54 +1100108 for (i = 0; i < n; i++) {
109 snprintf (namen, len + 8, "%s%x", name, i);
110 create_new_bitfield (namen, width);
111 }
112 free(namen);
113}
114
Denis 'GNUtoo' Carikli3cb25bb2018-01-11 16:47:33 +0100115static struct field *putsym (char const *sym_name, unsigned int w)
Damien Zammit06853222016-11-16 21:06:54 +1100116{
117 if (getsym(sym_name)) {
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +0100118 fprintf(stderr, "Cannot add duplicate named bitfield `%s`\n",
119 sym_name);
Damien Zammit06853222016-11-16 21:06:54 +1100120 return 0;
121 }
122 struct field *ptr = (struct field *) malloc (sizeof (struct field));
Martin Roth63381892017-04-09 13:30:17 -0600123 check_pointer(ptr);
Damien Zammit06853222016-11-16 21:06:54 +1100124 ptr->name = (char *) malloc (strlen (sym_name) + 1);
Martin Roth63381892017-04-09 13:30:17 -0600125 check_pointer(ptr->name);
Damien Zammit06853222016-11-16 21:06:54 +1100126 strcpy (ptr->name, sym_name);
127 ptr->width = w;
128 ptr->value = 0;
129 ptr->next = (struct field *)0;
130 if (sym_table_tail) {
131 sym_table_tail->next = ptr;
132 } else {
133 sym_table = ptr;
134 }
135 sym_table_tail = ptr;
136 return ptr;
137}
138
Denis 'GNUtoo' Carikli3cb25bb2018-01-11 16:47:33 +0100139static struct field *getsym (char const *sym_name)
Damien Zammit06853222016-11-16 21:06:54 +1100140{
141 struct field *ptr;
142 for (ptr = sym_table; ptr != (struct field *) 0;
143 ptr = (struct field *)ptr->next) {
144 if (strcmp (ptr->name, sym_name) == 0)
145 return ptr;
146 }
147 return 0;
148}
149
Martin Roth63381892017-04-09 13:30:17 -0600150static void dump_all_values (void)
Damien Zammit06853222016-11-16 21:06:54 +1100151{
152 struct field *ptr;
153 for (ptr = sym_table; ptr != (struct field *) 0;
154 ptr = (struct field *)ptr->next) {
155 fprintf(stderr, "%s = %d (%d bits)\n",
156 ptr->name,
157 ptr->value,
158 ptr->width);
159 }
160}
161
Martin Roth63381892017-04-09 13:30:17 -0600162static void empty_field_table(void)
Damien Zammit06853222016-11-16 21:06:54 +1100163{
164 struct field *ptr;
165 struct field *ptrnext;
166
167 for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptrnext) {
168 if (ptr) {
169 ptrnext = ptr->next;
170 free(ptr);
171 } else {
172 ptrnext = (struct field *) 0;
173 }
174 }
175 sym_table = 0;
176 sym_table_tail = 0;
177}
178
Martin Roth63381892017-04-09 13:30:17 -0600179static void create_binary_blob (void)
Damien Zammit06853222016-11-16 21:06:54 +1100180{
181 if (binary && binary->blb) {
182 free(binary->blb);
183 free(binary);
184 }
185 binary = (struct blob *) malloc (sizeof (struct blob));
Martin Roth63381892017-04-09 13:30:17 -0600186 check_pointer(binary);
Damien Zammit06853222016-11-16 21:06:54 +1100187 binary->blb = (unsigned char *) malloc (sizeof (unsigned char));
Martin Roth63381892017-04-09 13:30:17 -0600188 check_pointer(binary->blb);
Damien Zammit06853222016-11-16 21:06:54 +1100189 binary->bloblen = 0;
190 binary->blb[0] = VALID_BIT;
191}
192
Martin Roth63381892017-04-09 13:30:17 -0600193static void interpret_next_blob_value (struct field *f)
Damien Zammit06853222016-11-16 21:06:54 +1100194{
Martin Roth63381892017-04-09 13:30:17 -0600195 unsigned int i;
Damien Zammit06853222016-11-16 21:06:54 +1100196 unsigned int v = 0;
197
198 if (binary->bloblen >= binary->lenactualblob * 8) {
199 f->value = 0;
200 return;
201 }
202
203 for (i = 0; i < f->width; i++) {
204 v |= (binary->blb[binary->bloblen++] & 1) << i;
205 }
206
207 f->value = v;
208}
209
210/* {}%BIN -> {} */
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100211static void generate_setter_bitfields(FILE* fp, unsigned char *bin)
Damien Zammit06853222016-11-16 21:06:54 +1100212{
213 unsigned int i;
214 struct field *ptr;
215
216 /* Convert bytes to bit array */
217 for (i = 0; i < binary->lenactualblob; i++) {
218 append_field_to_blob (value_to_bits(bin[i], 8), 8);
219 }
220
221 /* Reset blob position to zero */
222 binary->bloblen = 0;
223
Denis 'GNUtoo' Carikli780e9312018-01-10 14:35:55 +0100224 fprintf (fp, "# AUTOGENERATED SETTER BY BINCFG\n{\n");
Damien Zammit06853222016-11-16 21:06:54 +1100225
226 /* Traverse spec and output bitfield setters based on blob values */
227 for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptr->next) {
228
229 interpret_next_blob_value(ptr);
230 fprintf (fp, "\t\"%s\" = 0x%x,\n", ptr->name, ptr->value);
231 }
232 fseek(fp, -2, SEEK_CUR);
233 fprintf (fp, "\n}\n");
234}
235
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100236static void generate_binary_with_gbe_checksum(FILE* fp)
Damien Zammit06853222016-11-16 21:06:54 +1100237{
238 int i;
239 unsigned short checksum;
240
241 /* traverse spec, push to blob and add up for checksum */
242 struct field *ptr;
243 unsigned int uptochksum = 0;
244 for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptr->next) {
245 if (strcmp (ptr->name, "checksum_gbe") == 0) {
246 /* Stop traversing because we hit checksum */
247 ptr = ptr->next;
248 break;
249 }
250 append_field_to_blob (
251 value_to_bits(ptr->value, ptr->width),
252 ptr->width);
253 uptochksum += ptr->width;
254 }
255
256 /* deserialize bits of blob up to checksum */
257 for (i = 0; i < uptochksum; i += 8) {
258 unsigned char byte = (((binary->blb[i+0] & 1) << 0)
259 | ((binary->blb[i+1] & 1) << 1)
260 | ((binary->blb[i+2] & 1) << 2)
261 | ((binary->blb[i+3] & 1) << 3)
262 | ((binary->blb[i+4] & 1) << 4)
263 | ((binary->blb[i+5] & 1) << 5)
264 | ((binary->blb[i+6] & 1) << 6)
265 | ((binary->blb[i+7] & 1) << 7)
266 );
267 fprintf(fp, "%c", byte);
268
269 /* incremental 16 bit checksum */
270 if ((i % 16) < 8) {
271 binary->checksum += byte;
272 } else {
273 binary->checksum += byte << 8;
274 }
275 }
276
277 checksum = (0xbaba - binary->checksum) & 0xffff;
278
279 /* Now write checksum */
280 set_bitfield ("checksum_gbe", checksum);
281
282 fprintf(fp, "%c", checksum & 0xff);
283 fprintf(fp, "%c", (checksum & 0xff00) >> 8);
284
285 append_field_to_blob (value_to_bits(checksum, 16), 16);
286
287 for (; ptr != (struct field *) 0; ptr = ptr->next) {
288 append_field_to_blob (
289 value_to_bits(ptr->value, ptr->width), ptr->width);
290 }
291
292 /* deserialize rest of blob past checksum */
293 for (i = uptochksum + CHECKSUM_SIZE; i < binary->bloblen; i += 8) {
294 unsigned char byte = (((binary->blb[i+0] & 1) << 0)
295 | ((binary->blb[i+1] & 1) << 1)
296 | ((binary->blb[i+2] & 1) << 2)
297 | ((binary->blb[i+3] & 1) << 3)
298 | ((binary->blb[i+4] & 1) << 4)
299 | ((binary->blb[i+5] & 1) << 5)
300 | ((binary->blb[i+6] & 1) << 6)
301 | ((binary->blb[i+7] & 1) << 7)
302 );
303 fprintf(fp, "%c", byte);
304 }
305}
306
307/* {}{} -> BIN */
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100308static void generate_binary(FILE* fp)
Damien Zammit06853222016-11-16 21:06:54 +1100309{
310 unsigned int i;
311 struct field *ptr;
312
313 if (binary->bloblen % 8) {
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +0100314 fprintf (stderr,
315 "ERROR: Spec must be multiple of 8 bits wide\n");
Damien Zammit06853222016-11-16 21:06:54 +1100316 exit (1);
317 }
318
319 if (getsym ("checksum_gbe")) {
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100320 generate_binary_with_gbe_checksum(fp);
Damien Zammit06853222016-11-16 21:06:54 +1100321 return;
322 }
323
324 /* traverse spec, push to blob */
325 for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptr->next) {
326 append_field_to_blob (
327 value_to_bits(ptr->value, ptr->width),
328 ptr->width);
329 }
330
331 /* deserialize bits of blob */
332 for (i = 0; i < binary->bloblen; i += 8) {
333 unsigned char byte = (((binary->blb[i+0] & 1) << 0)
334 | ((binary->blb[i+1] & 1) << 1)
335 | ((binary->blb[i+2] & 1) << 2)
336 | ((binary->blb[i+3] & 1) << 3)
337 | ((binary->blb[i+4] & 1) << 4)
338 | ((binary->blb[i+5] & 1) << 5)
339 | ((binary->blb[i+6] & 1) << 6)
340 | ((binary->blb[i+7] & 1) << 7)
341 );
342 fprintf(fp, "%c", byte);
343 }
344}
345
346%}
347
348%union
349{
350 char *str;
351 unsigned int u32;
352 unsigned int *u32array;
353 unsigned char u8;
354 unsigned char *u8array;
355}
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100356%parse-param {FILE* fp}
Damien Zammit06853222016-11-16 21:06:54 +1100357
358%token <str> name
359%token <u32> val
360%token <u32array> vals
361%token <u8> hexbyte
362%token <u8array> binblob
363%token <u8> eof
364
365%left '%'
366%left '{' '}'
367%left ','
368%left ':'
369%left '='
370
371%%
372
373input:
374 /* empty */
375| input spec setter eof { empty_field_table(); YYACCEPT;}
376| input spec blob { fprintf (stderr, "Parsed all bytes\n");
377 empty_field_table(); YYACCEPT;}
378;
379
380blob:
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100381 '%' eof { generate_setter_bitfields(fp,
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +0100382 binary->actualblob); }
Damien Zammit06853222016-11-16 21:06:54 +1100383;
384
385spec:
386 '{' '}' { fprintf (stderr, "No spec\n"); }
387| '{' specmembers '}' { fprintf (stderr, "Parsed all spec\n");
388 create_binary_blob(); }
389;
390
391specmembers:
392 specpair
393| specpair ',' specmembers
394;
395
396specpair:
397 name ':' val { create_new_bitfield($1, $3); }
398| name '[' val ']' ':' val { create_new_bitfields($1, $3, $6); }
399;
400
401setter:
402 '{' '}' { fprintf (stderr, "No values\n"); }
403| '{' valuemembers '}' { fprintf (stderr, "Parsed all values\n");
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100404 generate_binary(fp); }
Damien Zammit06853222016-11-16 21:06:54 +1100405;
406
407valuemembers:
408 setpair
409| setpair ',' valuemembers
410;
411
412setpair:
413 name '=' val { set_bitfield($1, $3); }
414| name '[' val ']' '=' val { set_bitfield_array($1, $3, $6); }
415;
416
417%%
418
419/* Called by yyparse on error. */
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100420static void yyerror (FILE* fp, char const *s)
Damien Zammit06853222016-11-16 21:06:54 +1100421{
422 fprintf (stderr, "yyerror: %s\n", s);
423}
424
425/* Declarations */
426void set_input_string(char* in);
427
428/* This function parses a string */
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100429static int parse_string(FILE* fp, unsigned char* in) {
Damien Zammit06853222016-11-16 21:06:54 +1100430 set_input_string ((char *)in);
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100431 return yyparse (fp);
Damien Zammit06853222016-11-16 21:06:54 +1100432}
433
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100434static unsigned int loadfile (FILE* fp, char *file, char *filetype,
Martin Roth63381892017-04-09 13:30:17 -0600435 unsigned char **parsestring, unsigned int lenstr)
436{
437 unsigned int lenfile;
438
439 if ((fp = fopen(file, "r")) == NULL) {
440 printf("Error: Could not open %s file: %s\n",filetype,file);
441 exit(1);
442 }
443 fseek(fp, 0, SEEK_END);
444 lenfile = ftell(fp);
445 fseek(fp, 0, SEEK_SET);
446
447 if (lenstr == 0)
448 *parsestring = (unsigned char *) malloc (lenfile + 2);
449 else
450 *parsestring = (unsigned char *) realloc (*parsestring,
451 lenfile + lenstr);
452
453 check_pointer(*parsestring);
454 fread(*parsestring + lenstr, 1, lenfile, fp);
455 fclose(fp);
456 return lenfile;
457}
458
Damien Zammit06853222016-11-16 21:06:54 +1100459int main (int argc, char *argv[])
460{
Martin Roth63381892017-04-09 13:30:17 -0600461 unsigned int lenspec;
Damien Zammit06853222016-11-16 21:06:54 +1100462 unsigned char *parsestring;
463 unsigned char c;
464 unsigned int pos = 0;
465 int ret = 0;
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100466 FILE* fp;
Damien Zammit06853222016-11-16 21:06:54 +1100467
468#if YYDEBUG == 1
469 yydebug = 1;
470#endif
471 create_binary_blob();
472 binary->lenactualblob = 0;
473
474 if (argc == 4 && strcmp(argv[1], "-d") != 0) {
475 /* Compile mode */
476
477 /* Load Spec */
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100478 lenspec = loadfile(fp, argv[1], "spec", &parsestring, 0);
479 loadfile(fp, argv[2], "setter", &parsestring, lenspec);
Damien Zammit06853222016-11-16 21:06:54 +1100480
481 /* Open output and parse string - output to fp */
Martin Roth63381892017-04-09 13:30:17 -0600482 if ((fp = fopen(argv[3], "wb")) == NULL) {
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +0100483 printf("Error: Could not open output file: %s\n",
484 argv[3]);
Martin Roth63381892017-04-09 13:30:17 -0600485 exit(1);
486 }
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100487 ret = parse_string(fp, parsestring);
Damien Zammit06853222016-11-16 21:06:54 +1100488 free(parsestring);
489 } else if (argc == 5 && strcmp (argv[1], "-d") == 0) {
490 /* Decompile mode */
491
492 /* Load Spec */
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100493 lenspec = loadfile(fp, argv[2], "spec", &parsestring, 0);
Damien Zammit06853222016-11-16 21:06:54 +1100494
Damien Zammit06853222016-11-16 21:06:54 +1100495 parsestring[lenspec] = '%';
Martin Roth63381892017-04-09 13:30:17 -0600496 parsestring[lenspec + 1] = '\0';
Damien Zammit06853222016-11-16 21:06:54 +1100497
498 /* Load Actual Binary */
Martin Roth63381892017-04-09 13:30:17 -0600499 if ((fp = fopen(argv[3], "rb")) == NULL) {
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +0100500 printf("Error: Could not open binary file: %s\n",
501 argv[3]);
Martin Roth63381892017-04-09 13:30:17 -0600502 exit(1);
503 }
Damien Zammit06853222016-11-16 21:06:54 +1100504 fseek(fp, 0, SEEK_END);
505 binary->lenactualblob = ftell(fp);
506 fseek(fp, 0, SEEK_SET);
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +0100507 binary->actualblob = (unsigned char *)malloc(
508 binary->lenactualblob);
Martin Roth63381892017-04-09 13:30:17 -0600509 check_pointer(binary->actualblob);
Damien Zammit06853222016-11-16 21:06:54 +1100510 fread(binary->actualblob, 1, binary->lenactualblob, fp);
511 fclose(fp);
512
513 /* Open output and parse - output to fp */
Martin Roth63381892017-04-09 13:30:17 -0600514 if ((fp = fopen(argv[4], "w")) == NULL) {
Denis 'GNUtoo' Cariklif73914d2018-01-12 05:24:23 +0100515 printf("Error: Could not open output file: %s\n",
516 argv[4]);
Martin Roth63381892017-04-09 13:30:17 -0600517 exit(1);
518 }
Denis 'GNUtoo' Cariklid5dee1e2018-01-12 04:21:14 +0100519 ret = parse_string(fp, parsestring);
Damien Zammit06853222016-11-16 21:06:54 +1100520 free(parsestring);
521 free(binary->actualblob);
522 fclose(fp);
523 } else {
524 printf("Usage: Compile mode\n\n");
Denis 'GNUtoo' Carikli780e9312018-01-10 14:35:55 +0100525 printf(" bincfg spec setter binaryoutput\n");
Damien Zammit06853222016-11-16 21:06:54 +1100526 printf(" (file) (file) (file)\n");
527 printf(" OR : Decompile mode\n\n");
Denis 'GNUtoo' Carikli780e9312018-01-10 14:35:55 +0100528 printf(" bincfg -d spec binary setteroutput\n");
Damien Zammit06853222016-11-16 21:06:54 +1100529 }
530 return ret;
531}