mb/google/parrot: Fix smbus subsystem ID
[coreboot.git] / util / bincfg / bincfg.y
blob43b3a00e0df270d22adec0213fdd26b25a533fc8
1 /* bincfg - Compiler/Decompiler for data blobs with specs */
2 /* SPDX-License-Identifier: GPL-3.0-or-later */
4 %{
5 #include <stdio.h>
6 #include <inttypes.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include "bincfg.h"
10 //#define YYDEBUG 1
12 static void check_pointer (void *ptr)
14 if (ptr == NULL) {
15 printf("Error: Out of memory\n");
16 exit(1);
20 static unsigned char* value_to_bits (unsigned int v, unsigned int w)
22 unsigned int i;
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);
33 return bitarr;
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)
39 unsigned int i, j;
40 binary->blb = (unsigned char *) realloc (binary->blb,
41 binary->bloblen + w);
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);
47 binary->bloblen += w;
50 static void set_bitfield(char *name, unsigned int value)
52 unsigned long long i;
53 struct field *bf = getsym (name);
54 if (bf) {
55 bf->value = value & 0xffffffff;
56 i = (1 << bf->width) - 1;
57 if (bf->width > 8 * sizeof (unsigned int)) {
58 fprintf(stderr,
59 "Overflow in bitfield, truncating bits to"
60 " fit\n");
61 bf->value = value & i;
63 //fprintf(stderr, "Setting `%s` = %d\n", bf->name, bf->value);
64 } else {
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)
71 unsigned int i;
72 unsigned long len = strlen (name);
73 char *namen = (char *) malloc ((len + 9) * sizeof (char));
74 check_pointer(namen);
75 for (i = 0; i < n; i++) {
76 snprintf (namen, len + 8, "%s%x", name, i);
77 set_bitfield (namen, value);
79 free(namen);
82 static void create_new_bitfield(char *name, unsigned int width)
84 struct field *bf;
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)
92 unsigned int i;
93 unsigned long len = strlen (name);
94 char *namen = (char *) malloc ((len + 9) * sizeof (char));
95 check_pointer(namen);
96 for (i = 0; i < n; i++) {
97 snprintf (namen, len + 8, "%s%x", name, i);
98 create_new_bitfield (namen, width);
100 free(namen);
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",
107 sym_name);
108 return 0;
110 struct field *ptr = (struct field *) malloc (sizeof (struct field));
111 check_pointer(ptr);
112 ptr->name = (char *) malloc (strlen (sym_name) + 1);
113 check_pointer(ptr->name);
114 strcpy (ptr->name, sym_name);
115 ptr->width = w;
116 ptr->value = 0;
117 ptr->next = (struct field *)0;
118 if (sym_table_tail) {
119 sym_table_tail->next = ptr;
120 } else {
121 sym_table = ptr;
123 sym_table_tail = ptr;
124 return ptr;
127 static struct field *getsym (char const *sym_name)
129 struct field *ptr;
130 for (ptr = sym_table; ptr != (struct field *) 0;
131 ptr = (struct field *)ptr->next) {
132 if (strcmp (ptr->name, sym_name) == 0)
133 return ptr;
135 return 0;
138 static void dump_all_values (void)
140 struct field *ptr;
141 for (ptr = sym_table; ptr != (struct field *) 0;
142 ptr = (struct field *)ptr->next) {
143 fprintf(stderr, "%s = %d (%d bits)\n",
144 ptr->name,
145 ptr->value,
146 ptr->width);
150 static void empty_field_table(void)
152 struct field *ptr;
153 struct field *ptrnext;
155 for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptrnext) {
156 if (ptr) {
157 ptrnext = ptr->next;
158 free(ptr);
159 } else {
160 ptrnext = (struct field *) 0;
163 sym_table = 0;
164 sym_table_tail = 0;
167 static void create_binary_blob (void)
169 if (binary && binary->blb) {
170 free(binary->blb);
171 free(binary);
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);
177 binary->bloblen = 0;
178 binary->blb[0] = VALID_BIT;
181 static void interpret_next_blob_value (struct field *f)
183 unsigned int i;
184 unsigned int v = 0;
186 if (binary->bloblen >= binary->lenactualblob * 8) {
187 f->value = 0;
188 return;
191 for (i = 0; i < f->width; i++) {
192 v |= (binary->blb[binary->bloblen++] & 1) << i;
195 f->value = v;
198 /* {}%BIN -> {} */
199 static void generate_setter_bitfields(FILE* fp, unsigned char *bin)
201 unsigned int i;
202 struct field *ptr;
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 */
210 binary->bloblen = 0;
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)
226 unsigned int i;
227 unsigned short checksum;
229 /* traverse spec, push to blob and add up for checksum */
230 struct field *ptr;
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 */
235 ptr = ptr->next;
236 break;
238 append_field_to_blob (
239 value_to_bits(ptr->value, ptr->width),
240 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 */
258 if ((i % 16) < 8) {
259 binary->checksum += byte;
260 } else {
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);
295 /* {}{} -> BIN */
296 static void generate_binary(FILE* fp)
298 unsigned int i;
299 struct field *ptr;
301 if (binary->bloblen % 8) {
302 fprintf (stderr,
303 "ERROR: Spec must be multiple of 8 bits wide\n");
304 exit (1);
307 if (getsym ("checksum_gbe")) {
308 generate_binary_with_gbe_checksum(fp);
309 return;
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),
316 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);
336 %union
338 char *str;
339 unsigned int u32;
340 unsigned int *u32array;
341 unsigned char u8;
342 unsigned char *u8array;
344 %parse-param {FILE* fp}
346 %token <str> name
347 %token <u32> val
348 %token <u32array> vals
349 %token <u8> hexbyte
350 %token <u8array> binblob
351 %token <u8> eof
353 %left '%'
354 %left '{' '}'
355 %left ','
356 %left ':'
357 %left '='
361 input:
362 /* empty */
363 | input spec setter eof { empty_field_table(); YYACCEPT;}
364 | input spec blob { fprintf (stderr, "Parsed all bytes\n");
365 empty_field_table(); YYACCEPT;}
368 blob:
369 '%' eof { generate_setter_bitfields(fp,
370 binary->actualblob); }
373 spec:
374 '{' '}' { fprintf (stderr, "No spec\n"); }
375 | '{' specmembers '}' { fprintf (stderr, "Parsed all spec\n");
376 create_binary_blob(); }
379 specmembers:
380 specpair
381 | specpair ',' specmembers
384 specpair:
385 name ':' val { create_new_bitfield($1, $3); }
386 | name '[' val ']' ':' val { create_new_bitfields($1, $3, $6); }
389 setter:
390 '{' '}' { fprintf (stderr, "No values\n"); }
391 | '{' valuemembers '}' { fprintf (stderr, "Parsed all values\n");
392 generate_binary(fp); }
395 valuemembers:
396 setpair
397 | setpair ',' valuemembers
400 setpair:
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)
410 (void)fp;
411 fprintf (stderr, "yyerror: %s\n", s);
414 /* Declarations */
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);
420 return yyparse (fp);
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);
430 exit(1);
432 fseek(fp, 0, SEEK_END);
433 lenfile = ftell(fp);
434 fseek(fp, 0, SEEK_SET);
436 if (lenstr == 0)
437 *parsestring = (unsigned char *) malloc (lenfile + 2);
438 else
439 *parsestring = (unsigned char *) realloc (*parsestring,
440 lenfile + lenstr);
442 check_pointer(*parsestring);
443 fread(*parsestring + lenstr, 1, lenfile, fp);
444 fclose(fp);
445 return lenfile;
448 int main (int argc, char *argv[])
450 unsigned int lenspec;
451 unsigned char *parsestring;
452 int ret = 0;
453 FILE* fp;
455 #if YYDEBUG == 1
456 yydebug = 1;
457 #endif
458 create_binary_blob();
459 binary->lenactualblob = 0;
461 if (argc == 4 && strcmp(argv[1], "-d") != 0) {
462 /* Compile mode */
464 /* Load Spec */
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",
471 argv[3]);
472 exit(1);
474 ret = parse_string(fp, parsestring);
475 free(parsestring);
476 } else if (argc == 5 && strcmp (argv[1], "-d") == 0) {
477 /* Decompile mode */
479 /* Load Spec */
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",
488 argv[3]);
489 exit(1);
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);
498 fclose(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",
503 argv[4]);
504 exit(1);
506 ret = parse_string(fp, parsestring);
507 free(parsestring);
508 free(binary->actualblob);
509 fclose(fp);
510 } else {
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");
517 return ret;