1 /* bincfg - Compiler/Decompiler for data blobs with specs */
2 /* SPDX-License-Identifier: GPL-3.0-or-later */
12 static void check_pointer
(void *ptr
)
15 printf
("Error: Out of memory\n");
20 static unsigned char* value_to_bits
(unsigned int v
, unsigned int w
)
23 unsigned char* bitarr
;
25 if
(w
> MAX_WIDTH
) w
= MAX_WIDTH
;
26 bitarr
= (unsigned char *) malloc
(w
* sizeof
(unsigned char));
27 check_pointer
(bitarr
);
28 memset
(bitarr
, 0, w
);
30 for
(i
= 0; i
< w
; i
++) {
31 bitarr
[i
] = VALID_BIT |
((v
& (1 << i
)) >> i
);
36 /* Store each bit of a bitfield in a new byte sequentially 0x80 or 0x81 */
37 static void append_field_to_blob
(unsigned char b
[], unsigned int w
)
40 binary
->blb
= (unsigned char *) realloc
(binary
->blb
,
42 check_pointer
(binary
->blb
);
43 for
(j
= 0, i
= binary
->bloblen
; i
< binary
->bloblen
+ w
; i
++, j
++) {
44 binary
->blb
[i
] = VALID_BIT |
(b
[j
] & 1);
45 //fprintf (stderr, "blob[%d] = %d\n", i, binary->blb[i] & 1);
50 static void set_bitfield
(char *name
, unsigned int value
)
53 struct field
*bf
= getsym
(name
);
55 bf
->value
= value
& 0xffffffff;
56 i
= (1 << bf
->width
) - 1;
57 if
(bf
->width
> 8 * sizeof
(unsigned int)) {
59 "Overflow in bitfield, truncating bits to"
61 bf
->value
= value
& i
;
63 //fprintf(stderr, "Setting `%s` = %d\n", bf->name, bf->value);
65 fprintf
(stderr
, "Can't find bitfield `%s` in spec\n", name
);
69 static void set_bitfield_array
(char *name
, unsigned int n
, unsigned int value
)
72 unsigned long len
= strlen
(name
);
73 char *namen
= (char *) malloc
((len
+ 9) * sizeof
(char));
75 for
(i
= 0; i
< n
; i
++) {
76 snprintf
(namen
, len
+ 8, "%s%x", name
, i
);
77 set_bitfield
(namen
, value
);
82 static void create_new_bitfield
(char *name
, unsigned int width
)
86 if
(!(bf
= putsym
(name
, width
))) return
;
87 //fprintf(stderr, "Added bitfield `%s` : %d\n", bf->name, width);
90 static void create_new_bitfields
(char *name
, unsigned int n
, unsigned int width
)
93 unsigned long len
= strlen
(name
);
94 char *namen
= (char *) malloc
((len
+ 9) * sizeof
(char));
96 for
(i
= 0; i
< n
; i
++) {
97 snprintf
(namen
, len
+ 8, "%s%x", name
, i
);
98 create_new_bitfield
(namen
, width
);
103 static struct field
*putsym
(char const *sym_name
, unsigned int w
)
105 if
(getsym
(sym_name
)) {
106 fprintf
(stderr
, "Cannot add duplicate named bitfield `%s`\n",
110 struct field
*ptr
= (struct field
*) malloc
(sizeof
(struct field
));
112 ptr
->name
= (char *) malloc
(strlen
(sym_name
) + 1);
113 check_pointer
(ptr
->name
);
114 strcpy
(ptr
->name
, sym_name
);
117 ptr
->next
= (struct field
*)0;
118 if
(sym_table_tail
) {
119 sym_table_tail
->next
= ptr
;
123 sym_table_tail
= ptr
;
127 static struct field
*getsym
(char const *sym_name
)
130 for
(ptr
= sym_table
; ptr
!= (struct field
*) 0;
131 ptr
= (struct field
*)ptr
->next
) {
132 if
(strcmp
(ptr
->name
, sym_name
) == 0)
138 static void dump_all_values
(void)
141 for
(ptr
= sym_table
; ptr
!= (struct field
*) 0;
142 ptr
= (struct field
*)ptr
->next
) {
143 fprintf
(stderr
, "%s = %d (%d bits)\n",
150 static void empty_field_table
(void)
153 struct field
*ptrnext
;
155 for
(ptr
= sym_table
; ptr
!= (struct field
*) 0; ptr
= ptrnext
) {
160 ptrnext
= (struct field
*) 0;
167 static void create_binary_blob
(void)
169 if
(binary
&& binary
->blb
) {
173 binary
= (struct blob
*) malloc
(sizeof
(struct blob
));
174 check_pointer
(binary
);
175 binary
->blb
= (unsigned char *) malloc
(sizeof
(unsigned char));
176 check_pointer
(binary
->blb
);
178 binary
->blb
[0] = VALID_BIT
;
181 static void interpret_next_blob_value
(struct field
*f
)
186 if
(binary
->bloblen
>= binary
->lenactualblob
* 8) {
191 for
(i
= 0; i
< f
->width
; i
++) {
192 v |
= (binary
->blb
[binary
->bloblen
++] & 1) << i
;
199 static void generate_setter_bitfields
(FILE* fp
, unsigned char *bin
)
204 /* Convert bytes to bit array */
205 for
(i
= 0; i
< binary
->lenactualblob
; i
++) {
206 append_field_to_blob
(value_to_bits
(bin
[i
], 8), 8);
209 /* Reset blob position to zero */
212 fprintf
(fp
, "# AUTOGENERATED SETTER BY BINCFG\n{\n");
214 /* Traverse spec and output bitfield setters based on blob values */
215 for
(ptr
= sym_table
; ptr
!= (struct field
*) 0; ptr
= ptr
->next
) {
217 interpret_next_blob_value
(ptr
);
218 fprintf
(fp
, "\t\"%s\" = 0x%x,\n", ptr
->name
, ptr
->value
);
220 fseek
(fp
, -2, SEEK_CUR
);
221 fprintf
(fp
, "\n}\n");
224 static void generate_binary_with_gbe_checksum
(FILE* fp
)
227 unsigned short checksum
;
229 /* traverse spec, push to blob and add up for checksum */
231 unsigned int uptochksum
= 0;
232 for
(ptr
= sym_table
; ptr
!= (struct field
*) 0; ptr
= ptr
->next
) {
233 if
(strcmp
(ptr
->name
, "checksum_gbe") == 0) {
234 /* Stop traversing because we hit checksum */
238 append_field_to_blob
(
239 value_to_bits
(ptr
->value
, ptr
->width
),
241 uptochksum
+= ptr
->width
;
244 /* deserialize bits of blob up to checksum */
245 for
(i
= 0; i
< uptochksum
; i
+= 8) {
246 unsigned char byte
= (((binary
->blb
[i
+0] & 1) << 0)
247 |
((binary
->blb
[i
+1] & 1) << 1)
248 |
((binary
->blb
[i
+2] & 1) << 2)
249 |
((binary
->blb
[i
+3] & 1) << 3)
250 |
((binary
->blb
[i
+4] & 1) << 4)
251 |
((binary
->blb
[i
+5] & 1) << 5)
252 |
((binary
->blb
[i
+6] & 1) << 6)
253 |
((binary
->blb
[i
+7] & 1) << 7)
255 fprintf
(fp
, "%c", byte
);
257 /* incremental 16 bit checksum */
259 binary
->checksum
+= byte
;
261 binary
->checksum
+= byte
<< 8;
265 checksum
= (0xbaba - binary
->checksum
) & 0xffff;
267 /* Now write checksum */
268 set_bitfield
("checksum_gbe", checksum
);
270 fprintf
(fp
, "%c", checksum
& 0xff);
271 fprintf
(fp
, "%c", (checksum
& 0xff00) >> 8);
273 append_field_to_blob
(value_to_bits
(checksum
, 16), 16);
275 for
(; ptr
!= (struct field
*) 0; ptr
= ptr
->next
) {
276 append_field_to_blob
(
277 value_to_bits
(ptr
->value
, ptr
->width
), ptr
->width
);
280 /* deserialize rest of blob past checksum */
281 for
(i
= uptochksum
+ CHECKSUM_SIZE
; i
< binary
->bloblen
; i
+= 8) {
282 unsigned char byte
= (((binary
->blb
[i
+0] & 1) << 0)
283 |
((binary
->blb
[i
+1] & 1) << 1)
284 |
((binary
->blb
[i
+2] & 1) << 2)
285 |
((binary
->blb
[i
+3] & 1) << 3)
286 |
((binary
->blb
[i
+4] & 1) << 4)
287 |
((binary
->blb
[i
+5] & 1) << 5)
288 |
((binary
->blb
[i
+6] & 1) << 6)
289 |
((binary
->blb
[i
+7] & 1) << 7)
291 fprintf
(fp
, "%c", byte
);
296 static void generate_binary
(FILE* fp
)
301 if
(binary
->bloblen %
8) {
303 "ERROR: Spec must be multiple of 8 bits wide\n");
307 if
(getsym
("checksum_gbe")) {
308 generate_binary_with_gbe_checksum
(fp
);
312 /* traverse spec, push to blob */
313 for
(ptr
= sym_table
; ptr
!= (struct field
*) 0; ptr
= ptr
->next
) {
314 append_field_to_blob
(
315 value_to_bits
(ptr
->value
, ptr
->width
),
319 /* deserialize bits of blob */
320 for
(i
= 0; i
< binary
->bloblen
; i
+= 8) {
321 unsigned char byte
= (((binary
->blb
[i
+0] & 1) << 0)
322 |
((binary
->blb
[i
+1] & 1) << 1)
323 |
((binary
->blb
[i
+2] & 1) << 2)
324 |
((binary
->blb
[i
+3] & 1) << 3)
325 |
((binary
->blb
[i
+4] & 1) << 4)
326 |
((binary
->blb
[i
+5] & 1) << 5)
327 |
((binary
->blb
[i
+6] & 1) << 6)
328 |
((binary
->blb
[i
+7] & 1) << 7)
330 fprintf
(fp
, "%c", byte
);
340 unsigned int *u32array
;
342 unsigned char *u8array
;
344 %parse
-param
{FILE* fp
}
348 %token
<u32array
> vals
350 %token
<u8array
> binblob
363 | input spec setter eof
{ empty_field_table
(); YYACCEPT;}
364 | input spec blob
{ fprintf
(stderr
, "Parsed all bytes\n");
365 empty_field_table
(); YYACCEPT;}
369 '%' eof
{ generate_setter_bitfields
(fp
,
370 binary
->actualblob
); }
374 '{' '}' { fprintf
(stderr
, "No spec\n"); }
375 |
'{' specmembers
'}' { fprintf
(stderr
, "Parsed all spec\n");
376 create_binary_blob
(); }
381 | specpair
',' specmembers
385 name
':' val
{ create_new_bitfield
($1, $3); }
386 | name
'[' val
']' ':' val
{ create_new_bitfields
($1, $3, $6); }
390 '{' '}' { fprintf
(stderr
, "No values\n"); }
391 |
'{' valuemembers
'}' { fprintf
(stderr
, "Parsed all values\n");
392 generate_binary
(fp
); }
397 | setpair
',' valuemembers
401 name
'=' val
{ set_bitfield
($1, $3); }
402 | name
'[' val
']' '=' val
{ set_bitfield_array
($1, $3, $6); }
407 /* Called by yyparse on error. */
408 static void yyerror (FILE* fp
, char const *s
)
411 fprintf
(stderr
, "yyerror: %s\n", s
);
415 void set_input_string
(char* in
);
417 /* This function parses a string */
418 static int parse_string
(FILE* fp
, unsigned char* in
) {
419 set_input_string
((char *)in
);
423 static unsigned int loadfile
(FILE* fp
, char *file
, char *filetype
,
424 unsigned char **parsestring
, unsigned int lenstr
)
426 unsigned int lenfile
;
428 if
((fp
= fopen
(file
, "r")) == NULL
) {
429 printf
("Error: Could not open %s file: %s\n",filetype
,file
);
432 fseek
(fp
, 0, SEEK_END
);
434 fseek
(fp
, 0, SEEK_SET
);
437 *parsestring
= (unsigned char *) malloc
(lenfile
+ 2);
439 *parsestring
= (unsigned char *) realloc
(*parsestring
,
442 check_pointer
(*parsestring
);
443 fread
(*parsestring
+ lenstr
, 1, lenfile
, fp
);
448 int main
(int argc
, char *argv
[])
450 unsigned int lenspec
;
451 unsigned char *parsestring
;
458 create_binary_blob
();
459 binary
->lenactualblob
= 0;
461 if
(argc
== 4 && strcmp
(argv
[1], "-d") != 0) {
465 lenspec
= loadfile
(fp
, argv
[1], "spec", &parsestring
, 0);
466 loadfile
(fp
, argv
[2], "setter", &parsestring
, lenspec
);
468 /* Open output and parse string - output to fp */
469 if
((fp
= fopen
(argv
[3], "wb")) == NULL
) {
470 printf
("Error: Could not open output file: %s\n",
474 ret
= parse_string
(fp
, parsestring
);
476 } else if
(argc
== 5 && strcmp
(argv
[1], "-d") == 0) {
480 lenspec
= loadfile
(fp
, argv
[2], "spec", &parsestring
, 0);
482 parsestring
[lenspec
] = '%';
483 parsestring
[lenspec
+ 1] = '\0';
485 /* Load Actual Binary */
486 if
((fp
= fopen
(argv
[3], "rb")) == NULL
) {
487 printf
("Error: Could not open binary file: %s\n",
491 fseek
(fp
, 0, SEEK_END
);
492 binary
->lenactualblob
= ftell
(fp
);
493 fseek
(fp
, 0, SEEK_SET
);
494 binary
->actualblob
= (unsigned char *)malloc
(
495 binary
->lenactualblob
);
496 check_pointer
(binary
->actualblob
);
497 fread
(binary
->actualblob
, 1, binary
->lenactualblob
, fp
);
500 /* Open output and parse - output to fp */
501 if
((fp
= fopen
(argv
[4], "w")) == NULL
) {
502 printf
("Error: Could not open output file: %s\n",
506 ret
= parse_string
(fp
, parsestring
);
508 free
(binary
->actualblob
);
511 printf
("Usage: Compile mode\n\n");
512 printf
(" bincfg spec setter binaryoutput\n");
513 printf
(" (file) (file) (file)\n");
514 printf
(" OR : Decompile mode\n\n");
515 printf
(" bincfg -d spec binary setteroutput\n");