Given a specification of bitfields defined e.g. as follows:
	specfile:
		{
			"field1" : 8,
			"field2" : 4,
			"field3" : 4
		}
and a set of values for setting defaults:
	setterfile:
		{
			"field1" = 0xff,
			"field2" = 0xf,
			"field3" = 0xf
		}
You can generate a binary packed blob as follows:
	./blobtool specfile setterfile binaryoutput
	binaryoutput:	ff ff
The reverse is also possible, i.e. you can regenerate the setter:
	./blobtool -d specfile binaryoutput setterorig
	setterorig:
		# AUTOGENERATED SETTER BY BLOBTOOL
		{
			"field1" = 0xff,
			"field2" = 0xf,
			"field3" = 0xf
		}
This tool comes with spec/set files for X200 flash descriptor
and ICH9M GbE region, and can be extended or used to decompile
other data blobs with known specs.
Change-Id: I744d6b421003feb4fc460133603af7e6bd80b1d6
Signed-off-by: Damien Zammit <damien@zamaudio.com>
Reviewed-on: https://review.coreboot.org/17445
Tested-by: build bot (Jenkins)
Reviewed-by: Jonathan Neuschäfer <j.neuschaefer@gmx.net>
Reviewed-by: Martin Roth <martinroth@google.com>
		
	
		
			
				
	
	
		
			146 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
/*
 | 
						|
 * 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 <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include "blobtool.tab.h"
 | 
						|
 | 
						|
extern struct blob binary;
 | 
						|
 | 
						|
unsigned int parsehex (char *s)
 | 
						|
{
 | 
						|
	unsigned int i, nib, val = 0;
 | 
						|
	unsigned int nibs = strlen(s) - 2;
 | 
						|
 | 
						|
	for (i = 2; i < nibs + 2; i++) {
 | 
						|
		if (s[i] >= '0' && s[i] <= '9') {
 | 
						|
			nib = s[i] - '0';
 | 
						|
		} else if (s[i] >= 'a' && s[i] <= 'f') {
 | 
						|
			nib = s[i] - 'a' + 10;
 | 
						|
		} else if (s[i] >= 'A' && s[i] <= 'F') {
 | 
						|
			nib = s[i] - 'A' + 10;
 | 
						|
		} else {
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
		val |= nib << (((nibs - 1) - (i - 2)) * 4);
 | 
						|
	}
 | 
						|
	return val;
 | 
						|
}
 | 
						|
 | 
						|
char* stripquotes (char *string)
 | 
						|
{
 | 
						|
	char *stripped;
 | 
						|
	unsigned int len = strlen(string);
 | 
						|
	if (len >= 2 && string[0] == '\"' && string[len-1] == '\"') {
 | 
						|
		stripped = (char *) malloc (len - 2 + 1);
 | 
						|
		snprintf (stripped, len - 2 + 1, "%s", string+1);
 | 
						|
		stripped[len-2] = '\0';
 | 
						|
		return stripped;
 | 
						|
	} else {
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
%}
 | 
						|
 | 
						|
%option noyywrap
 | 
						|
%option nounput
 | 
						|
 | 
						|
DIGIT1to9 [1-9]
 | 
						|
DIGIT [0-9]
 | 
						|
DIGITS {DIGIT}+
 | 
						|
INT {DIGIT}|{DIGIT1to9}{DIGITS}|-{DIGIT}|-{DIGIT1to9}{DIGITS}
 | 
						|
FRAC [.]{DIGITS}
 | 
						|
E [eE][+-]?
 | 
						|
EXP {E}{DIGITS}
 | 
						|
HEX_DIGIT [0-9a-fA-F]
 | 
						|
HEX_DIGITS {HEX_DIGIT}+
 | 
						|
NUMBER {INT}|{INT}{FRAC}|{INT}{EXP}|{INT}{FRAC}{EXP}
 | 
						|
UNICODECHAR \\u{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}{HEX_DIGIT}
 | 
						|
ALPHA [a-zA-Z]
 | 
						|
SPECIAL [()\[\]"'@_\-+:;/\\.,<> 	]
 | 
						|
VARCHAR {ALPHA}|{DIGIT}|{SPECIAL}
 | 
						|
CHAR {VARCHAR}|{UNICODECHAR}
 | 
						|
CHARS {CHAR}+
 | 
						|
QUOTE ["]
 | 
						|
HEX_PREFIX [0][x]
 | 
						|
HEX {HEX_PREFIX}{HEX_DIGITS}
 | 
						|
STRING {QUOTE}{QUOTE}|{QUOTE}{CHARS}{QUOTE}
 | 
						|
COMMENT [#]{CHARS}[\n]|[#]\n
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
{STRING} {
 | 
						|
    yylval.str = stripquotes(yytext);
 | 
						|
    return name;
 | 
						|
};
 | 
						|
 | 
						|
{NUMBER} {
 | 
						|
    yylval.u32 = atoi(yytext);
 | 
						|
    return val;
 | 
						|
};
 | 
						|
 | 
						|
{HEX} {
 | 
						|
    yylval.u32 = parsehex(yytext);
 | 
						|
    return val;
 | 
						|
};
 | 
						|
 | 
						|
\{ {
 | 
						|
    return '{';
 | 
						|
};
 | 
						|
 | 
						|
\} {
 | 
						|
    return '}';
 | 
						|
};
 | 
						|
 | 
						|
\[ {
 | 
						|
    return '[';
 | 
						|
};
 | 
						|
 | 
						|
\] {
 | 
						|
    return ']';
 | 
						|
};
 | 
						|
 | 
						|
, {
 | 
						|
    return ',';
 | 
						|
};
 | 
						|
 | 
						|
: {
 | 
						|
    return ':';
 | 
						|
};
 | 
						|
 | 
						|
= {
 | 
						|
    return '=';
 | 
						|
};
 | 
						|
 | 
						|
[ \t\n]+ /* ignore whitespace */;
 | 
						|
 | 
						|
{COMMENT} /* ignore comments */
 | 
						|
 | 
						|
\% {
 | 
						|
    return '%';
 | 
						|
};
 | 
						|
 | 
						|
<<EOF>> { return eof; };
 | 
						|
 | 
						|
%%
 | 
						|
 | 
						|
void set_input_string(char* in) {
 | 
						|
	yy_scan_string(in);
 | 
						|
}
 | 
						|
 |