diff options
Diffstat (limited to 'util/blobtool/blobtool.y')
-rw-r--r-- | util/blobtool/blobtool.y | 551 |
1 files changed, 0 insertions, 551 deletions
diff --git a/util/blobtool/blobtool.y b/util/blobtool/blobtool.y deleted file mode 100644 index 11f8db4886..0000000000 --- a/util/blobtool/blobtool.y +++ /dev/null @@ -1,551 +0,0 @@ -/* - * blobtool - Compiler/Decompiler for data blobs with specs - * Copyright (C) 2017 Damien Zammit <damien@zamaudio.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -%{ -#include <stdio.h> -#include <inttypes.h> -#include <stdlib.h> -#include <string.h> -//#define YYDEBUG 1 -int yylex (void); -void yyerror (char const *); - -struct field { - char *name; - unsigned int width; - unsigned int value; - struct field *next; -}; - -extern struct field *sym_table; -struct field *putsym (char const *, unsigned int); -struct field *getsym (char const *); - -struct field *sym_table; -struct field *sym_table_tail; - -FILE* fp; - -/* Bit array intermediary representation */ -struct blob { - unsigned int bloblen; - unsigned char *blb; - unsigned short checksum; - unsigned char *actualblob; - unsigned int lenactualblob; -}; - -#define VALID_BIT 0x80 -#define MAX_WIDTH 32 -#define CHECKSUM_SIZE 16 - -struct blob *binary; - -static void check_pointer (void *ptr) -{ - if (ptr == NULL) { - printf("Error: Out of memory\n"); - exit(1); - } -} - -static unsigned char* value_to_bits (unsigned int v, unsigned int w) -{ - unsigned int i; - unsigned char* bitarr; - - if (w > MAX_WIDTH) w = MAX_WIDTH; - bitarr = (unsigned char *) malloc (w * sizeof (unsigned char)); - check_pointer(bitarr); - memset (bitarr, 0, w); - - for (i = 0; i < w; i++) { - bitarr[i] = VALID_BIT | ((v & (1 << i)) >> i); - } - return bitarr; -} - -/* Store each bit of a bitfield in a new byte sequentially 0x80 or 0x81 */ -static void append_field_to_blob (unsigned char b[], unsigned int w) -{ - unsigned int i, j; - binary->blb = (unsigned char *) realloc (binary->blb, binary->bloblen + w); - check_pointer(binary->blb); - for (j = 0, i = binary->bloblen; i < binary->bloblen + w; i++, j++) { - binary->blb[i] = VALID_BIT | (b[j] & 1); - //fprintf (stderr, "blob[%d] = %d\n", i, binary->blb[i] & 1); - } - binary->bloblen += w; -} - -static void set_bitfield(char *name, unsigned int value) -{ - unsigned long long i; - struct field *bf = getsym (name); - if (bf) { - bf->value = value & 0xffffffff; - i = (1 << bf->width) - 1; - if (bf->width > 8 * sizeof (unsigned int)) { - fprintf(stderr, "Overflow in bitfield, truncating bits to fit\n"); - bf->value = value & i; - } - //fprintf(stderr, "Setting `%s` = %d\n", bf->name, bf->value); - } else { - fprintf(stderr, "Can't find bitfield `%s` in spec\n", name); - } -} - -static void set_bitfield_array(char *name, unsigned int n, unsigned int value) -{ - unsigned int i; - unsigned long len = strlen (name); - char *namen = (char *) malloc ((len + 9) * sizeof (char)); - check_pointer(namen); - for (i = 0; i < n; i++) { - snprintf (namen, len + 8, "%s%x", name, i); - set_bitfield (namen, value); - } - free(namen); -} - -static void create_new_bitfield(char *name, unsigned int width) -{ - struct field *bf; - - if (!(bf = putsym (name, width))) return; - //fprintf(stderr, "Added bitfield `%s` : %d\n", bf->name, width); -} - -static void create_new_bitfields(char *name, unsigned int n, unsigned int width) -{ - unsigned int i; - unsigned long len = strlen (name); - char *namen = (char *) malloc ((len + 9) * sizeof (char)); - check_pointer(namen); - for (i = 0; i < n; i++) { - snprintf (namen, len + 8, "%s%x", name, i); - create_new_bitfield (namen, width); - } - free(namen); -} - -struct field *putsym (char const *sym_name, unsigned int w) -{ - if (getsym(sym_name)) { - fprintf(stderr, "Cannot add duplicate named bitfield `%s`\n", sym_name); - return 0; - } - struct field *ptr = (struct field *) malloc (sizeof (struct field)); - check_pointer(ptr); - ptr->name = (char *) malloc (strlen (sym_name) + 1); - check_pointer(ptr->name); - strcpy (ptr->name, sym_name); - ptr->width = w; - ptr->value = 0; - ptr->next = (struct field *)0; - if (sym_table_tail) { - sym_table_tail->next = ptr; - } else { - sym_table = ptr; - } - sym_table_tail = ptr; - return ptr; -} - -struct field *getsym (char const *sym_name) -{ - struct field *ptr; - for (ptr = sym_table; ptr != (struct field *) 0; - ptr = (struct field *)ptr->next) { - if (strcmp (ptr->name, sym_name) == 0) - return ptr; - } - return 0; -} - -static void dump_all_values (void) -{ - struct field *ptr; - for (ptr = sym_table; ptr != (struct field *) 0; - ptr = (struct field *)ptr->next) { - fprintf(stderr, "%s = %d (%d bits)\n", - ptr->name, - ptr->value, - ptr->width); - } -} - -static void empty_field_table(void) -{ - struct field *ptr; - struct field *ptrnext; - - for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptrnext) { - if (ptr) { - ptrnext = ptr->next; - free(ptr); - } else { - ptrnext = (struct field *) 0; - } - } - sym_table = 0; - sym_table_tail = 0; -} - -static void create_binary_blob (void) -{ - if (binary && binary->blb) { - free(binary->blb); - free(binary); - } - binary = (struct blob *) malloc (sizeof (struct blob)); - check_pointer(binary); - binary->blb = (unsigned char *) malloc (sizeof (unsigned char)); - check_pointer(binary->blb); - binary->bloblen = 0; - binary->blb[0] = VALID_BIT; -} - -static void interpret_next_blob_value (struct field *f) -{ - unsigned int i; - unsigned int v = 0; - - if (binary->bloblen >= binary->lenactualblob * 8) { - f->value = 0; - return; - } - - for (i = 0; i < f->width; i++) { - v |= (binary->blb[binary->bloblen++] & 1) << i; - } - - f->value = v; -} - -/* {}%BIN -> {} */ -static void generate_setter_bitfields(unsigned char *bin) -{ - unsigned int i; - struct field *ptr; - - /* Convert bytes to bit array */ - for (i = 0; i < binary->lenactualblob; i++) { - append_field_to_blob (value_to_bits(bin[i], 8), 8); - } - - /* Reset blob position to zero */ - binary->bloblen = 0; - - fprintf (fp, "# AUTOGENERATED SETTER BY BLOBTOOL\n{\n"); - - /* Traverse spec and output bitfield setters based on blob values */ - for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptr->next) { - - interpret_next_blob_value(ptr); - fprintf (fp, "\t\"%s\" = 0x%x,\n", ptr->name, ptr->value); - } - fseek(fp, -2, SEEK_CUR); - fprintf (fp, "\n}\n"); -} - -static void generate_binary_with_gbe_checksum(void) -{ - int i; - unsigned short checksum; - - /* traverse spec, push to blob and add up for checksum */ - struct field *ptr; - unsigned int uptochksum = 0; - for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptr->next) { - if (strcmp (ptr->name, "checksum_gbe") == 0) { - /* Stop traversing because we hit checksum */ - ptr = ptr->next; - break; - } - append_field_to_blob ( - value_to_bits(ptr->value, ptr->width), - ptr->width); - uptochksum += ptr->width; - } - - /* deserialize bits of blob up to checksum */ - for (i = 0; i < uptochksum; i += 8) { - unsigned char byte = (((binary->blb[i+0] & 1) << 0) - | ((binary->blb[i+1] & 1) << 1) - | ((binary->blb[i+2] & 1) << 2) - | ((binary->blb[i+3] & 1) << 3) - | ((binary->blb[i+4] & 1) << 4) - | ((binary->blb[i+5] & 1) << 5) - | ((binary->blb[i+6] & 1) << 6) - | ((binary->blb[i+7] & 1) << 7) - ); - fprintf(fp, "%c", byte); - - /* incremental 16 bit checksum */ - if ((i % 16) < 8) { - binary->checksum += byte; - } else { - binary->checksum += byte << 8; - } - } - - checksum = (0xbaba - binary->checksum) & 0xffff; - - /* Now write checksum */ - set_bitfield ("checksum_gbe", checksum); - - fprintf(fp, "%c", checksum & 0xff); - fprintf(fp, "%c", (checksum & 0xff00) >> 8); - - append_field_to_blob (value_to_bits(checksum, 16), 16); - - for (; ptr != (struct field *) 0; ptr = ptr->next) { - append_field_to_blob ( - value_to_bits(ptr->value, ptr->width), ptr->width); - } - - /* deserialize rest of blob past checksum */ - for (i = uptochksum + CHECKSUM_SIZE; i < binary->bloblen; i += 8) { - unsigned char byte = (((binary->blb[i+0] & 1) << 0) - | ((binary->blb[i+1] & 1) << 1) - | ((binary->blb[i+2] & 1) << 2) - | ((binary->blb[i+3] & 1) << 3) - | ((binary->blb[i+4] & 1) << 4) - | ((binary->blb[i+5] & 1) << 5) - | ((binary->blb[i+6] & 1) << 6) - | ((binary->blb[i+7] & 1) << 7) - ); - fprintf(fp, "%c", byte); - } -} - -/* {}{} -> BIN */ -static void generate_binary(void) -{ - unsigned int i; - struct field *ptr; - - if (binary->bloblen % 8) { - fprintf (stderr, "ERROR: Spec must be multiple of 8 bits wide\n"); - exit (1); - } - - if (getsym ("checksum_gbe")) { - generate_binary_with_gbe_checksum(); - return; - } - - /* traverse spec, push to blob */ - for (ptr = sym_table; ptr != (struct field *) 0; ptr = ptr->next) { - append_field_to_blob ( - value_to_bits(ptr->value, ptr->width), - ptr->width); - } - - /* deserialize bits of blob */ - for (i = 0; i < binary->bloblen; i += 8) { - unsigned char byte = (((binary->blb[i+0] & 1) << 0) - | ((binary->blb[i+1] & 1) << 1) - | ((binary->blb[i+2] & 1) << 2) - | ((binary->blb[i+3] & 1) << 3) - | ((binary->blb[i+4] & 1) << 4) - | ((binary->blb[i+5] & 1) << 5) - | ((binary->blb[i+6] & 1) << 6) - | ((binary->blb[i+7] & 1) << 7) - ); - fprintf(fp, "%c", byte); - } -} - -%} - -%union -{ - char *str; - unsigned int u32; - unsigned int *u32array; - unsigned char u8; - unsigned char *u8array; -} - -%token <str> name -%token <u32> val -%token <u32array> vals -%token <u8> hexbyte -%token <u8array> binblob -%token <u8> eof - -%left '%' -%left '{' '}' -%left ',' -%left ':' -%left '=' - -%% - -input: - /* empty */ -| input spec setter eof { empty_field_table(); YYACCEPT;} -| input spec blob { fprintf (stderr, "Parsed all bytes\n"); - empty_field_table(); YYACCEPT;} -; - -blob: - '%' eof { generate_setter_bitfields(binary->actualblob); } -; - -spec: - '{' '}' { fprintf (stderr, "No spec\n"); } -| '{' specmembers '}' { fprintf (stderr, "Parsed all spec\n"); - create_binary_blob(); } -; - -specmembers: - specpair -| specpair ',' specmembers -; - -specpair: - name ':' val { create_new_bitfield($1, $3); } -| name '[' val ']' ':' val { create_new_bitfields($1, $3, $6); } -; - -setter: - '{' '}' { fprintf (stderr, "No values\n"); } -| '{' valuemembers '}' { fprintf (stderr, "Parsed all values\n"); - generate_binary(); } -; - -valuemembers: - setpair -| setpair ',' valuemembers -; - -setpair: - name '=' val { set_bitfield($1, $3); } -| name '[' val ']' '=' val { set_bitfield_array($1, $3, $6); } -; - -%% - -/* Called by yyparse on error. */ -void yyerror (char const *s) -{ - fprintf (stderr, "yyerror: %s\n", s); -} - -/* Declarations */ -void set_input_string(char* in); - -/* This function parses a string */ -static int parse_string(unsigned char* in) { - set_input_string ((char *)in); - return yyparse (); -} - -static unsigned int loadfile (char *file, char *filetype, - unsigned char **parsestring, unsigned int lenstr) -{ - unsigned int lenfile; - - if ((fp = fopen(file, "r")) == NULL) { - printf("Error: Could not open %s file: %s\n",filetype,file); - exit(1); - } - fseek(fp, 0, SEEK_END); - lenfile = ftell(fp); - fseek(fp, 0, SEEK_SET); - - if (lenstr == 0) - *parsestring = (unsigned char *) malloc (lenfile + 2); - else - *parsestring = (unsigned char *) realloc (*parsestring, - lenfile + lenstr); - - check_pointer(*parsestring); - fread(*parsestring + lenstr, 1, lenfile, fp); - fclose(fp); - return lenfile; -} - -int main (int argc, char *argv[]) -{ - unsigned int lenspec; - unsigned char *parsestring; - unsigned char c; - unsigned int pos = 0; - int ret = 0; - -#if YYDEBUG == 1 - yydebug = 1; -#endif - create_binary_blob(); - binary->lenactualblob = 0; - - if (argc == 4 && strcmp(argv[1], "-d") != 0) { - /* Compile mode */ - - /* Load Spec */ - lenspec = loadfile(argv[1], "spec", &parsestring, 0); - loadfile(argv[2], "setter", &parsestring, lenspec); - - /* Open output and parse string - output to fp */ - if ((fp = fopen(argv[3], "wb")) == NULL) { - printf("Error: Could not open output file: %s\n",argv[3]); - exit(1); - } - ret = parse_string(parsestring); - free(parsestring); - } else if (argc == 5 && strcmp (argv[1], "-d") == 0) { - /* Decompile mode */ - - /* Load Spec */ - lenspec = loadfile(argv[2], "spec", &parsestring, 0); - - parsestring[lenspec] = '%'; - parsestring[lenspec + 1] = '\0'; - - /* Load Actual Binary */ - if ((fp = fopen(argv[3], "rb")) == NULL) { - printf("Error: Could not open binary file: %s\n",argv[3]); - exit(1); - } - fseek(fp, 0, SEEK_END); - binary->lenactualblob = ftell(fp); - fseek(fp, 0, SEEK_SET); - binary->actualblob = (unsigned char *) malloc (binary->lenactualblob); - check_pointer(binary->actualblob); - fread(binary->actualblob, 1, binary->lenactualblob, fp); - fclose(fp); - - /* Open output and parse - output to fp */ - if ((fp = fopen(argv[4], "w")) == NULL) { - printf("Error: Could not open output file: %s\n",argv[4]); - exit(1); - } - ret = parse_string(parsestring); - free(parsestring); - free(binary->actualblob); - fclose(fp); - } else { - printf("Usage: Compile mode\n\n"); - printf(" blobtool spec setter binaryoutput\n"); - printf(" (file) (file) (file)\n"); - printf(" OR : Decompile mode\n\n"); - printf(" blobtool -d spec binary setteroutput\n"); - } - return ret; -} |