2020-05-08 19:28:13 +02:00
|
|
|
/* bincfg - Compiler/Decompiler for data blobs with specs */
|
util/: Replace GPLv2 boiler plate with SPDX header
Used commands:
perl -i -p0e 's|\/\*[\s*]*.*is free software[:;][\s*]*you[\s*]*can[\s*]*redistribute[\s*]*it[\s*]*and\/or[\s*]*modify[\s*]*it[\s*]*under[\s*]*the[\s*]*terms[\s*]*of[\s*]*the[\s*]*GNU[\s*]*General[\s*]*Public[\s*]*License[\s*]*as[\s*]*published[\s*]*by[\s*]*the[\s*]*Free[\s*]*Software[\s*]*Foundation[;,][\s*]*version[\s*]*2[\s*]*of[\s*]*the[\s*]*License.[\s*]*This[\s*]*program[\s*]*is[\s*]*distributed[\s*]*in[\s*]*the[\s*]*hope[\s*]*that[\s*]*it[\s*]*will[\s*]*be[\s*]*useful,[\s*]*but[\s*]*WITHOUT[\s*]*ANY[\s*]*WARRANTY;[\s*]*without[\s*]*even[\s*]*the[\s*]*implied[\s*]*warranty[\s*]*of[\s*]*MERCHANTABILITY[\s*]*or[\s*]*FITNESS[\s*]*FOR[\s*]*A[\s*]*PARTICULAR[\s*]*PURPOSE.[\s*]*See[\s*]*the[\s*]*GNU[\s*]*General[\s*]*Public[\s*]*License[\s*]*for[\s*]*more[\s*]*details.[\s*]*\*\/|/* SPDX-License-Identifier: GPL-2.0-only */|' $(cat filelist)
perl -i -p0e 's|This[\s*]*program[\s*]*is[\s*]*free[\s*]*software[:;][\s*]*you[\s*]*can[\s*]*redistribute[\s*]*it[\s*]*and/or[\s*]*modify[\s*]*it[\s*]*under[\s*]*the[\s*]*terms[\s*]*of[\s*]*the[\s*]*GNU[\s*]*General[\s*]*Public[\s*]*License[\s*]*as[\s*]*published[\s*]*by[\s*]*the[\s*]*Free[\s*]*Software[\s*]*Foundation[;,][\s*]*either[\s*]*version[\s*]*2[\s*]*of[\s*]*the[\s*]*License,[\s*]*or[\s*]*.at[\s*]*your[\s*]*option.*[\s*]*any[\s*]*later[\s*]*version.[\s*]*This[\s*]*program[\s*]*is[\s*]*distributed[\s*]*in[\s*]*the[\s*]*hope[\s*]*that[\s*]*it[\s*]*will[\s*]*be[\s*]*useful,[\s*]*but[\s*]*WITHOUT[\s*]*ANY[\s*]*WARRANTY;[\s*]*without[\s*]*even[\s*]*the[\s*]*implied[\s*]*warranty[\s*]*of[\s*]*MERCHANTABILITY[\s*]*or[\s*]*FITNESS[\s*]*FOR[\s*]*A[\s*]*PARTICULAR[\s*]*PURPOSE.[\s*]*See[\s*]*the[\s*]*GNU[\s*]*General[\s*]*Public[\s*]*License[\s*]*for[\s*]*more[\s*]*details.[\s*]*\*\/|/* SPDX-License-Identifier: GPL-2.0-or-later */|' $(cat filelist)
perl -i -p0e 's|\/\*[\s*]*.*This[\s*#]*program[\s*#]*is[\s*#]*free[\s*#]*software[;:,][\s*#]*you[\s*#]*can[\s*#]*redistribute[\s*#]*it[\s*#]*and/or[\s*#]*modify[\s*#]*it[\s*#]*under[\s*#]*the[\s*#]*terms[\s*#]*of[\s*#]*the[\s*#]*GNU[\s*#]*General[\s*#]*Public[\s*#]*License[\s*#]*as[\s*#]*published[\s*#]*by[\s*#]*the[\s*#]*Free[\s*#]*Software[\s*#]*Foundation[;:,][\s*#]*either[\s*#]*version[\s*#]*3[\s*#]*of[\s*#]*the[\s*#]*License[;:,][\s*#]*or[\s*#]*.at[\s*#]*your[\s*#]*option.*[\s*#]*any[\s*#]*later[\s*#]*version.[\s*#]*This[\s*#]*program[\s*#]*is[\s*#]*distributed[\s*#]*in[\s*#]*the[\s*#]*hope[\s*#]*that[\s*#]*it[\s*#]*will[\s*#]*be[\s*#]*useful[;:,][\s*#]*but[\s*#]*WITHOUT[\s*#]*ANY[\s*#]*WARRANTY[;:,][\s*#]*without[\s*#]*even[\s*#]*the[\s*#]*implied[\s*#]*warranty[\s*#]*of[\s*#]*MERCHANTABILITY[\s*#]*or[\s*#]*FITNESS[\s*#]*FOR[\s*#]*A[\s*#]*PARTICULAR[\s*#]*PURPOSE.[\s*#]*See[\s*#]*the[\s*#]*GNU[\s*#]*General[\s*#]*Public[\s*#]*License[\s*#]*for[\s*#]*more[\s*#]*details.[\s*]*\*\/|/* SPDX-License-Identifier: GPL-3.0-or-later */|' $(cat filelist)
perl -i -p0e 's|(\#\#*)[\w]*.*is free software[:;][\#\s]*you[\#\s]*can[\#\s]*redistribute[\#\s]*it[\#\s]*and\/or[\#\s]*modify[\#\s]*it[\s\#]*under[\s \#]*the[\s\#]*terms[\s\#]*of[\s\#]*the[\s\#]*GNU[\s\#]*General[\s\#]*Public[\s\#]*License[\s\#]*as[\s\#]*published[\s\#]*by[\s\#]*the[\s\#]*Free[\s\#]*Software[\s\#]*Foundation[;,][\s\#]*version[\s\#]*2[\s\#]*of[\s\#]*the[\s\#]*License.*[\s\#]*This[\s\#]*program[\s\#]*is[\s\#]*distributed[\s\#]*in[\s\#]*the[\s\#]*hope[\s\#]*that[\s\#]*it[\s\#]*will[\#\s]*be[\#\s]*useful,[\#\s]*but[\#\s]*WITHOUT[\#\s]*ANY[\#\s]*WARRANTY;[\#\s]*without[\#\s]*even[\#\s]*the[\#\s]*implied[\#\s]*warranty[\#\s]*of[\#\s]*MERCHANTABILITY[\#\s]*or[\#\s]*FITNESS[\#\s]*FOR[\#\s]*A[\#\s]*PARTICULAR[\#\s]*PURPOSE.[\#\s]*See[\#\s]*the[\#\s]*GNU[\#\s]*General[\#\s]*Public[\#\s]*License[\#\s]*for[\#\s]*more[\#\s]*details.\s(#* *\n)*|\1 SPDX-License-Identifier: GPL-2.0-only\n\n|' $(cat filelist)
perl -i -p0e 's|(\#\#*)[\w*]*.*is free software[:;][\s*]*you[\s*]*can[\s*]*redistribute[\s*]*it[\s*]*and\/or[\s*]*modify[\s*]*it[\s*]*under[\s*]*the[\s*]*terms[\s*]*of[\s*]*the[\s*]*GNU[\s*]*General[\s*]*Public[\s*]*License[\s*]*as[\s*]*published[\s*]*by[\s*]*the[\s*]*Free[\s*]*Software[\s*]*Foundation[;,][\s*]*version[\s*]*2[\s*]*of[\s*]*the[\s*]*License.[\s*]*This[\s*]*program[\s*]*is[\s*]*distributed[\s*]*in[\s*]*the[\s*]*hope[\s*]*that[\s*]*it[\s*]*will[\s*]*be[\s*]*useful,[\s*]*but[\s*]*WITHOUT[\s*]*ANY[\s*]*WARRANTY;[\s*]*without[\s*]*even[\s*]*the[\s*]*implied[\s*]*warranty[\s*]*of[\s*]*MERCHANTABILITY[\s*]*or[\s*]*FITNESS[\s*]*FOR[\s*]*A[\s*]*PARTICULAR[\s*]*PURPOSE.[\s*]*See[\s*]*the[\s*]*GNU[\s*]*General[\s*]*Public[\s*]*License[\s*]*for[\s*]*more[\s*]*details.\s(#* *\n)*|\1 SPDX-License-Identifier: GPL-2.0-only\n\n|' $(cat filelist)
Change-Id: I1008a63b804f355a916221ac994701d7584f60ff
Signed-off-by: Patrick Georgi <pgeorgi@google.com>
Signed-off-by: Elyes HAOUAS <ehaouas@noos.fr>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41177
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
2020-05-08 20:48:04 +02:00
|
|
|
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
2016-11-16 11:06:54 +01:00
|
|
|
|
|
|
|
%{
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2018-01-12 04:04:30 +01:00
|
|
|
#include "bincfg.h"
|
2016-11-16 11:06:54 +01:00
|
|
|
//#define YYDEBUG 1
|
|
|
|
|
2017-04-09 21:30:17 +02:00
|
|
|
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)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
unsigned char* bitarr;
|
|
|
|
|
|
|
|
if (w > MAX_WIDTH) w = MAX_WIDTH;
|
|
|
|
bitarr = (unsigned char *) malloc (w * sizeof (unsigned char));
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(bitarr);
|
2016-11-16 11:06:54 +01:00
|
|
|
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 */
|
2017-04-09 21:30:17 +02:00
|
|
|
static void append_field_to_blob (unsigned char b[], unsigned int w)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
unsigned int i, j;
|
2018-01-12 05:24:23 +01:00
|
|
|
binary->blb = (unsigned char *) realloc (binary->blb,
|
|
|
|
binary->bloblen + w);
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(binary->blb);
|
2016-11-16 11:06:54 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static void set_bitfield(char *name, unsigned int value)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
unsigned long long i;
|
2019-01-26 11:09:13 +01:00
|
|
|
struct field *bf = getsym (name);
|
2016-11-16 11:06:54 +01:00
|
|
|
if (bf) {
|
|
|
|
bf->value = value & 0xffffffff;
|
|
|
|
i = (1 << bf->width) - 1;
|
|
|
|
if (bf->width > 8 * sizeof (unsigned int)) {
|
2018-01-12 05:24:23 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
"Overflow in bitfield, truncating bits to"
|
|
|
|
" fit\n");
|
2016-11-16 11:06:54 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static void set_bitfield_array(char *name, unsigned int n, unsigned int value)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
unsigned int i;
|
2017-04-09 21:30:17 +02:00
|
|
|
unsigned long len = strlen (name);
|
2016-11-16 11:06:54 +01:00
|
|
|
char *namen = (char *) malloc ((len + 9) * sizeof (char));
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(namen);
|
2016-11-16 11:06:54 +01:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
snprintf (namen, len + 8, "%s%x", name, i);
|
2019-01-26 11:09:13 +01:00
|
|
|
set_bitfield (namen, value);
|
2016-11-16 11:06:54 +01:00
|
|
|
}
|
|
|
|
free(namen);
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static void create_new_bitfield(char *name, unsigned int width)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
struct field *bf;
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
if (!(bf = putsym (name, width))) return;
|
2016-11-16 11:06:54 +01:00
|
|
|
//fprintf(stderr, "Added bitfield `%s` : %d\n", bf->name, width);
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static void create_new_bitfields(char *name, unsigned int n, unsigned int width)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
unsigned int i;
|
2017-04-09 21:30:17 +02:00
|
|
|
unsigned long len = strlen (name);
|
2016-11-16 11:06:54 +01:00
|
|
|
char *namen = (char *) malloc ((len + 9) * sizeof (char));
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(namen);
|
2016-11-16 11:06:54 +01:00
|
|
|
for (i = 0; i < n; i++) {
|
|
|
|
snprintf (namen, len + 8, "%s%x", name, i);
|
2019-01-26 11:09:13 +01:00
|
|
|
create_new_bitfield (namen, width);
|
2016-11-16 11:06:54 +01:00
|
|
|
}
|
|
|
|
free(namen);
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static struct field *putsym (char const *sym_name, unsigned int w)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
2019-01-26 11:09:13 +01:00
|
|
|
if (getsym(sym_name)) {
|
2018-01-12 05:24:23 +01:00
|
|
|
fprintf(stderr, "Cannot add duplicate named bitfield `%s`\n",
|
|
|
|
sym_name);
|
2016-11-16 11:06:54 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2019-01-26 11:09:13 +01:00
|
|
|
struct field *ptr = (struct field *) malloc (sizeof (struct field));
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(ptr);
|
2016-11-16 11:06:54 +01:00
|
|
|
ptr->name = (char *) malloc (strlen (sym_name) + 1);
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(ptr->name);
|
2016-11-16 11:06:54 +01:00
|
|
|
strcpy (ptr->name, sym_name);
|
|
|
|
ptr->width = w;
|
|
|
|
ptr->value = 0;
|
2019-01-26 11:09:13 +01:00
|
|
|
ptr->next = (struct field *)0;
|
2016-11-16 11:06:54 +01:00
|
|
|
if (sym_table_tail) {
|
|
|
|
sym_table_tail->next = ptr;
|
|
|
|
} else {
|
2019-01-26 11:09:13 +01:00
|
|
|
sym_table = ptr;
|
2016-11-16 11:06:54 +01:00
|
|
|
}
|
|
|
|
sym_table_tail = ptr;
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static struct field *getsym (char const *sym_name)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static void dump_all_values (void)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static void empty_field_table(void)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-04-09 21:30:17 +02:00
|
|
|
static void create_binary_blob (void)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
if (binary && binary->blb) {
|
|
|
|
free(binary->blb);
|
|
|
|
free(binary);
|
|
|
|
}
|
|
|
|
binary = (struct blob *) malloc (sizeof (struct blob));
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(binary);
|
2016-11-16 11:06:54 +01:00
|
|
|
binary->blb = (unsigned char *) malloc (sizeof (unsigned char));
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(binary->blb);
|
2016-11-16 11:06:54 +01:00
|
|
|
binary->bloblen = 0;
|
|
|
|
binary->blb[0] = VALID_BIT;
|
|
|
|
}
|
|
|
|
|
2017-04-09 21:30:17 +02:00
|
|
|
static void interpret_next_blob_value (struct field *f)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
2017-04-09 21:30:17 +02:00
|
|
|
unsigned int i;
|
2016-11-16 11:06:54 +01:00
|
|
|
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 -> {} */
|
2019-01-26 11:09:13 +01:00
|
|
|
static void generate_setter_bitfields(FILE* fp, unsigned char *bin)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2018-01-10 14:35:55 +01:00
|
|
|
fprintf (fp, "# AUTOGENERATED SETTER BY BINCFG\n{\n");
|
2016-11-16 11:06:54 +01:00
|
|
|
|
|
|
|
/* 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");
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
static void generate_binary_with_gbe_checksum(FILE* fp)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
2021-02-14 07:19:51 +01:00
|
|
|
unsigned int i;
|
2016-11-16 11:06:54 +01:00
|
|
|
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 */
|
2019-01-26 11:09:13 +01:00
|
|
|
set_bitfield ("checksum_gbe", checksum);
|
2016-11-16 11:06:54 +01:00
|
|
|
|
|
|
|
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 */
|
2019-01-26 11:09:13 +01:00
|
|
|
static void generate_binary(FILE* fp)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
struct field *ptr;
|
|
|
|
|
|
|
|
if (binary->bloblen % 8) {
|
2018-01-12 05:24:23 +01:00
|
|
|
fprintf (stderr,
|
|
|
|
"ERROR: Spec must be multiple of 8 bits wide\n");
|
2016-11-16 11:06:54 +01:00
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
|
2019-01-26 11:09:13 +01:00
|
|
|
if (getsym ("checksum_gbe")) {
|
|
|
|
generate_binary_with_gbe_checksum(fp);
|
2016-11-16 11:06:54 +01:00
|
|
|
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;
|
|
|
|
}
|
2019-01-26 11:09:13 +01:00
|
|
|
%parse-param {FILE* fp}
|
2016-11-16 11:06:54 +01:00
|
|
|
|
|
|
|
%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 */
|
2019-01-26 11:09:13 +01:00
|
|
|
| input spec setter eof { empty_field_table(); YYACCEPT;}
|
2016-11-16 11:06:54 +01:00
|
|
|
| input spec blob { fprintf (stderr, "Parsed all bytes\n");
|
2019-01-26 11:09:13 +01:00
|
|
|
empty_field_table(); YYACCEPT;}
|
2016-11-16 11:06:54 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
blob:
|
2019-01-26 11:09:13 +01:00
|
|
|
'%' eof { generate_setter_bitfields(fp,
|
2018-01-12 05:24:23 +01:00
|
|
|
binary->actualblob); }
|
2016-11-16 11:06:54 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
spec:
|
|
|
|
'{' '}' { fprintf (stderr, "No spec\n"); }
|
|
|
|
| '{' specmembers '}' { fprintf (stderr, "Parsed all spec\n");
|
|
|
|
create_binary_blob(); }
|
|
|
|
;
|
|
|
|
|
|
|
|
specmembers:
|
|
|
|
specpair
|
|
|
|
| specpair ',' specmembers
|
|
|
|
;
|
|
|
|
|
|
|
|
specpair:
|
2019-01-26 11:09:13 +01:00
|
|
|
name ':' val { create_new_bitfield($1, $3); }
|
|
|
|
| name '[' val ']' ':' val { create_new_bitfields($1, $3, $6); }
|
2016-11-16 11:06:54 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
setter:
|
|
|
|
'{' '}' { fprintf (stderr, "No values\n"); }
|
|
|
|
| '{' valuemembers '}' { fprintf (stderr, "Parsed all values\n");
|
2019-01-26 11:09:13 +01:00
|
|
|
generate_binary(fp); }
|
2016-11-16 11:06:54 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
valuemembers:
|
|
|
|
setpair
|
|
|
|
| setpair ',' valuemembers
|
|
|
|
;
|
|
|
|
|
|
|
|
setpair:
|
2019-01-26 11:09:13 +01:00
|
|
|
name '=' val { set_bitfield($1, $3); }
|
|
|
|
| name '[' val ']' '=' val { set_bitfield_array($1, $3, $6); }
|
2016-11-16 11:06:54 +01:00
|
|
|
;
|
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
/* Called by yyparse on error. */
|
2019-01-26 11:09:13 +01:00
|
|
|
static void yyerror (FILE* fp, char const *s)
|
2016-11-16 11:06:54 +01:00
|
|
|
{
|
2021-02-14 07:19:51 +01:00
|
|
|
(void)fp;
|
2016-11-16 11:06:54 +01:00
|
|
|
fprintf (stderr, "yyerror: %s\n", s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Declarations */
|
|
|
|
void set_input_string(char* in);
|
|
|
|
|
|
|
|
/* This function parses a string */
|
2019-01-26 11:09:13 +01:00
|
|
|
static int parse_string(FILE* fp, unsigned char* in) {
|
2016-11-16 11:06:54 +01:00
|
|
|
set_input_string ((char *)in);
|
2019-01-26 11:09:13 +01:00
|
|
|
return yyparse (fp);
|
2016-11-16 11:06:54 +01:00
|
|
|
}
|
|
|
|
|
2018-01-12 04:21:14 +01:00
|
|
|
static unsigned int loadfile (FILE* fp, char *file, char *filetype,
|
2017-04-09 21:30:17 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-11-16 11:06:54 +01:00
|
|
|
int main (int argc, char *argv[])
|
|
|
|
{
|
2017-04-09 21:30:17 +02:00
|
|
|
unsigned int lenspec;
|
2016-11-16 11:06:54 +01:00
|
|
|
unsigned char *parsestring;
|
|
|
|
int ret = 0;
|
2018-01-12 04:21:14 +01:00
|
|
|
FILE* fp;
|
2016-11-16 11:06:54 +01:00
|
|
|
|
|
|
|
#if YYDEBUG == 1
|
|
|
|
yydebug = 1;
|
|
|
|
#endif
|
|
|
|
create_binary_blob();
|
|
|
|
binary->lenactualblob = 0;
|
|
|
|
|
|
|
|
if (argc == 4 && strcmp(argv[1], "-d") != 0) {
|
|
|
|
/* Compile mode */
|
|
|
|
|
|
|
|
/* Load Spec */
|
2018-01-12 04:21:14 +01:00
|
|
|
lenspec = loadfile(fp, argv[1], "spec", &parsestring, 0);
|
|
|
|
loadfile(fp, argv[2], "setter", &parsestring, lenspec);
|
2016-11-16 11:06:54 +01:00
|
|
|
|
2017-04-09 21:30:17 +02:00
|
|
|
/* Open output and parse string - output to fp */
|
|
|
|
if ((fp = fopen(argv[3], "wb")) == NULL) {
|
2018-01-12 05:24:23 +01:00
|
|
|
printf("Error: Could not open output file: %s\n",
|
|
|
|
argv[3]);
|
2016-11-16 11:06:54 +01:00
|
|
|
exit(1);
|
|
|
|
}
|
2019-01-26 11:09:13 +01:00
|
|
|
ret = parse_string(fp, parsestring);
|
2016-11-16 11:06:54 +01:00
|
|
|
free(parsestring);
|
|
|
|
} else if (argc == 5 && strcmp (argv[1], "-d") == 0) {
|
|
|
|
/* Decompile mode */
|
|
|
|
|
|
|
|
/* Load Spec */
|
2018-01-12 04:21:14 +01:00
|
|
|
lenspec = loadfile(fp, argv[2], "spec", &parsestring, 0);
|
2016-11-16 11:06:54 +01:00
|
|
|
|
|
|
|
parsestring[lenspec] = '%';
|
2017-04-09 21:30:17 +02:00
|
|
|
parsestring[lenspec + 1] = '\0';
|
2016-11-16 11:06:54 +01:00
|
|
|
|
|
|
|
/* Load Actual Binary */
|
2017-04-09 21:30:17 +02:00
|
|
|
if ((fp = fopen(argv[3], "rb")) == NULL) {
|
2018-01-12 05:24:23 +01:00
|
|
|
printf("Error: Could not open binary file: %s\n",
|
|
|
|
argv[3]);
|
2017-04-09 21:30:17 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2016-11-16 11:06:54 +01:00
|
|
|
fseek(fp, 0, SEEK_END);
|
|
|
|
binary->lenactualblob = ftell(fp);
|
|
|
|
fseek(fp, 0, SEEK_SET);
|
2018-01-12 05:24:23 +01:00
|
|
|
binary->actualblob = (unsigned char *)malloc(
|
|
|
|
binary->lenactualblob);
|
2017-04-09 21:30:17 +02:00
|
|
|
check_pointer(binary->actualblob);
|
2016-11-16 11:06:54 +01:00
|
|
|
fread(binary->actualblob, 1, binary->lenactualblob, fp);
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
/* Open output and parse - output to fp */
|
2017-04-09 21:30:17 +02:00
|
|
|
if ((fp = fopen(argv[4], "w")) == NULL) {
|
2018-01-12 05:24:23 +01:00
|
|
|
printf("Error: Could not open output file: %s\n",
|
|
|
|
argv[4]);
|
2017-04-09 21:30:17 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
2019-01-26 11:09:13 +01:00
|
|
|
ret = parse_string(fp, parsestring);
|
2016-11-16 11:06:54 +01:00
|
|
|
free(parsestring);
|
|
|
|
free(binary->actualblob);
|
|
|
|
fclose(fp);
|
|
|
|
} else {
|
|
|
|
printf("Usage: Compile mode\n\n");
|
2018-01-10 14:35:55 +01:00
|
|
|
printf(" bincfg spec setter binaryoutput\n");
|
2016-11-16 11:06:54 +01:00
|
|
|
printf(" (file) (file) (file)\n");
|
|
|
|
printf(" OR : Decompile mode\n\n");
|
2018-01-10 14:35:55 +01:00
|
|
|
printf(" bincfg -d spec binary setteroutput\n");
|
2016-11-16 11:06:54 +01:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|