cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dtc-parser.y (10817B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
      4 */
      5%locations
      6
      7%{
      8#include <stdio.h>
      9#include <inttypes.h>
     10
     11#include "dtc.h"
     12#include "srcpos.h"
     13
     14extern int yylex(void);
     15extern void yyerror(char const *s);
     16#define ERROR(loc, ...) \
     17	do { \
     18		srcpos_error((loc), "Error", __VA_ARGS__); \
     19		treesource_error = true; \
     20	} while (0)
     21
     22#define YYERROR_CALL(msg) yyerror(msg)
     23
     24extern struct dt_info *parser_output;
     25extern bool treesource_error;
     26%}
     27
     28%union {
     29	char *propnodename;
     30	char *labelref;
     31	uint8_t byte;
     32	struct data data;
     33
     34	struct {
     35		struct data	data;
     36		int		bits;
     37	} array;
     38
     39	struct property *prop;
     40	struct property *proplist;
     41	struct node *node;
     42	struct node *nodelist;
     43	struct reserve_info *re;
     44	uint64_t integer;
     45	unsigned int flags;
     46}
     47
     48%token DT_V1
     49%token DT_PLUGIN
     50%token DT_MEMRESERVE
     51%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
     52%token DT_BITS
     53%token DT_DEL_PROP
     54%token DT_DEL_NODE
     55%token DT_OMIT_NO_REF
     56%token <propnodename> DT_PROPNODENAME
     57%token <integer> DT_LITERAL
     58%token <integer> DT_CHAR_LITERAL
     59%token <byte> DT_BYTE
     60%token <data> DT_STRING
     61%token <labelref> DT_LABEL
     62%token <labelref> DT_LABEL_REF
     63%token <labelref> DT_PATH_REF
     64%token DT_INCBIN
     65
     66%type <data> propdata
     67%type <data> propdataprefix
     68%type <flags> header
     69%type <flags> headers
     70%type <re> memreserve
     71%type <re> memreserves
     72%type <array> arrayprefix
     73%type <data> bytestring
     74%type <prop> propdef
     75%type <proplist> proplist
     76%type <labelref> dt_ref
     77
     78%type <node> devicetree
     79%type <node> nodedef
     80%type <node> subnode
     81%type <nodelist> subnodes
     82
     83%type <integer> integer_prim
     84%type <integer> integer_unary
     85%type <integer> integer_mul
     86%type <integer> integer_add
     87%type <integer> integer_shift
     88%type <integer> integer_rela
     89%type <integer> integer_eq
     90%type <integer> integer_bitand
     91%type <integer> integer_bitxor
     92%type <integer> integer_bitor
     93%type <integer> integer_and
     94%type <integer> integer_or
     95%type <integer> integer_trinary
     96%type <integer> integer_expr
     97
     98%%
     99
    100sourcefile:
    101	  headers memreserves devicetree
    102		{
    103			parser_output = build_dt_info($1, $2, $3,
    104			                              guess_boot_cpuid($3));
    105		}
    106	;
    107
    108header:
    109	  DT_V1 ';'
    110		{
    111			$$ = DTSF_V1;
    112		}
    113	| DT_V1 ';' DT_PLUGIN ';'
    114		{
    115			$$ = DTSF_V1 | DTSF_PLUGIN;
    116		}
    117	;
    118
    119headers:
    120	  header
    121	| header headers
    122		{
    123			if ($2 != $1)
    124				ERROR(&@2, "Header flags don't match earlier ones");
    125			$$ = $1;
    126		}
    127	;
    128
    129memreserves:
    130	  /* empty */
    131		{
    132			$$ = NULL;
    133		}
    134	| memreserve memreserves
    135		{
    136			$$ = chain_reserve_entry($1, $2);
    137		}
    138	;
    139
    140memreserve:
    141	  DT_MEMRESERVE integer_prim integer_prim ';'
    142		{
    143			$$ = build_reserve_entry($2, $3);
    144		}
    145	| DT_LABEL memreserve
    146		{
    147			add_label(&$2->labels, $1);
    148			$$ = $2;
    149		}
    150	;
    151
    152dt_ref: DT_LABEL_REF | DT_PATH_REF;
    153
    154devicetree:
    155	  '/' nodedef
    156		{
    157			$$ = name_node($2, "");
    158		}
    159	| devicetree '/' nodedef
    160		{
    161			$$ = merge_nodes($1, $3);
    162		}
    163	| dt_ref nodedef
    164		{
    165			/*
    166			 * We rely on the rule being always:
    167			 *   versioninfo plugindecl memreserves devicetree
    168			 * so $-1 is what we want (plugindecl)
    169			 */
    170			if (!($<flags>-1 & DTSF_PLUGIN))
    171				ERROR(&@2, "Label or path %s not found", $1);
    172			$$ = add_orphan_node(
    173					name_node(build_node(NULL, NULL, NULL),
    174						  ""),
    175					$2, $1);
    176		}
    177	| devicetree DT_LABEL dt_ref nodedef
    178		{
    179			struct node *target = get_node_by_ref($1, $3);
    180
    181			if (target) {
    182				add_label(&target->labels, $2);
    183				merge_nodes(target, $4);
    184			} else
    185				ERROR(&@3, "Label or path %s not found", $3);
    186			$$ = $1;
    187		}
    188	| devicetree DT_PATH_REF nodedef
    189		{
    190			/*
    191			 * We rely on the rule being always:
    192			 *   versioninfo plugindecl memreserves devicetree
    193			 * so $-1 is what we want (plugindecl)
    194			 */
    195			if ($<flags>-1 & DTSF_PLUGIN) {
    196				add_orphan_node($1, $3, $2);
    197			} else {
    198				struct node *target = get_node_by_ref($1, $2);
    199
    200				if (target)
    201					merge_nodes(target, $3);
    202				else
    203					ERROR(&@2, "Label or path %s not found", $2);
    204			}
    205			$$ = $1;
    206		}
    207	| devicetree DT_LABEL_REF nodedef
    208		{
    209			struct node *target = get_node_by_ref($1, $2);
    210
    211			if (target) {
    212				merge_nodes(target, $3);
    213			} else {
    214				/*
    215				 * We rely on the rule being always:
    216				 *   versioninfo plugindecl memreserves devicetree
    217				 * so $-1 is what we want (plugindecl)
    218				 */
    219				if ($<flags>-1 & DTSF_PLUGIN)
    220					add_orphan_node($1, $3, $2);
    221				else
    222					ERROR(&@2, "Label or path %s not found", $2);
    223			}
    224			$$ = $1;
    225		}
    226	| devicetree DT_DEL_NODE dt_ref ';'
    227		{
    228			struct node *target = get_node_by_ref($1, $3);
    229
    230			if (target)
    231				delete_node(target);
    232			else
    233				ERROR(&@3, "Label or path %s not found", $3);
    234
    235
    236			$$ = $1;
    237		}
    238	| devicetree DT_OMIT_NO_REF dt_ref ';'
    239		{
    240			struct node *target = get_node_by_ref($1, $3);
    241
    242			if (target)
    243				omit_node_if_unused(target);
    244			else
    245				ERROR(&@3, "Label or path %s not found", $3);
    246
    247
    248			$$ = $1;
    249		}
    250	;
    251
    252nodedef:
    253	  '{' proplist subnodes '}' ';'
    254		{
    255			$$ = build_node($2, $3, &@$);
    256		}
    257	;
    258
    259proplist:
    260	  /* empty */
    261		{
    262			$$ = NULL;
    263		}
    264	| proplist propdef
    265		{
    266			$$ = chain_property($2, $1);
    267		}
    268	;
    269
    270propdef:
    271	  DT_PROPNODENAME '=' propdata ';'
    272		{
    273			$$ = build_property($1, $3, &@$);
    274		}
    275	| DT_PROPNODENAME ';'
    276		{
    277			$$ = build_property($1, empty_data, &@$);
    278		}
    279	| DT_DEL_PROP DT_PROPNODENAME ';'
    280		{
    281			$$ = build_property_delete($2);
    282		}
    283	| DT_LABEL propdef
    284		{
    285			add_label(&$2->labels, $1);
    286			$$ = $2;
    287		}
    288	;
    289
    290propdata:
    291	  propdataprefix DT_STRING
    292		{
    293			$$ = data_merge($1, $2);
    294		}
    295	| propdataprefix arrayprefix '>'
    296		{
    297			$$ = data_merge($1, $2.data);
    298		}
    299	| propdataprefix '[' bytestring ']'
    300		{
    301			$$ = data_merge($1, $3);
    302		}
    303	| propdataprefix dt_ref
    304		{
    305			$1 = data_add_marker($1, TYPE_STRING, $2);
    306			$$ = data_add_marker($1, REF_PATH, $2);
    307		}
    308	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
    309		{
    310			FILE *f = srcfile_relative_open($4.val, NULL);
    311			struct data d;
    312
    313			if ($6 != 0)
    314				if (fseek(f, $6, SEEK_SET) != 0)
    315					die("Couldn't seek to offset %llu in \"%s\": %s",
    316					    (unsigned long long)$6, $4.val,
    317					    strerror(errno));
    318
    319			d = data_copy_file(f, $8);
    320
    321			$$ = data_merge($1, d);
    322			fclose(f);
    323		}
    324	| propdataprefix DT_INCBIN '(' DT_STRING ')'
    325		{
    326			FILE *f = srcfile_relative_open($4.val, NULL);
    327			struct data d = empty_data;
    328
    329			d = data_copy_file(f, -1);
    330
    331			$$ = data_merge($1, d);
    332			fclose(f);
    333		}
    334	| propdata DT_LABEL
    335		{
    336			$$ = data_add_marker($1, LABEL, $2);
    337		}
    338	;
    339
    340propdataprefix:
    341	  /* empty */
    342		{
    343			$$ = empty_data;
    344		}
    345	| propdata ','
    346		{
    347			$$ = $1;
    348		}
    349	| propdataprefix DT_LABEL
    350		{
    351			$$ = data_add_marker($1, LABEL, $2);
    352		}
    353	;
    354
    355arrayprefix:
    356	DT_BITS DT_LITERAL '<'
    357		{
    358			unsigned long long bits;
    359			enum markertype type = TYPE_UINT32;
    360
    361			bits = $2;
    362
    363			switch (bits) {
    364			case 8: type = TYPE_UINT8; break;
    365			case 16: type = TYPE_UINT16; break;
    366			case 32: type = TYPE_UINT32; break;
    367			case 64: type = TYPE_UINT64; break;
    368			default:
    369				ERROR(&@2, "Array elements must be"
    370				      " 8, 16, 32 or 64-bits");
    371				bits = 32;
    372			}
    373
    374			$$.data = data_add_marker(empty_data, type, NULL);
    375			$$.bits = bits;
    376		}
    377	| '<'
    378		{
    379			$$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
    380			$$.bits = 32;
    381		}
    382	| arrayprefix integer_prim
    383		{
    384			if ($1.bits < 64) {
    385				uint64_t mask = (1ULL << $1.bits) - 1;
    386				/*
    387				 * Bits above mask must either be all zero
    388				 * (positive within range of mask) or all one
    389				 * (negative and sign-extended). The second
    390				 * condition is true if when we set all bits
    391				 * within the mask to one (i.e. | in the
    392				 * mask), all bits are one.
    393				 */
    394				if (($2 > mask) && (($2 | mask) != -1ULL))
    395					ERROR(&@2, "Value out of range for"
    396					      " %d-bit array element", $1.bits);
    397			}
    398
    399			$$.data = data_append_integer($1.data, $2, $1.bits);
    400		}
    401	| arrayprefix dt_ref
    402		{
    403			uint64_t val = ~0ULL >> (64 - $1.bits);
    404
    405			if ($1.bits == 32)
    406				$1.data = data_add_marker($1.data,
    407							  REF_PHANDLE,
    408							  $2);
    409			else
    410				ERROR(&@2, "References are only allowed in "
    411					    "arrays with 32-bit elements.");
    412
    413			$$.data = data_append_integer($1.data, val, $1.bits);
    414		}
    415	| arrayprefix DT_LABEL
    416		{
    417			$$.data = data_add_marker($1.data, LABEL, $2);
    418		}
    419	;
    420
    421integer_prim:
    422	  DT_LITERAL
    423	| DT_CHAR_LITERAL
    424	| '(' integer_expr ')'
    425		{
    426			$$ = $2;
    427		}
    428	;
    429
    430integer_expr:
    431	integer_trinary
    432	;
    433
    434integer_trinary:
    435	  integer_or
    436	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
    437	;
    438
    439integer_or:
    440	  integer_and
    441	| integer_or DT_OR integer_and { $$ = $1 || $3; }
    442	;
    443
    444integer_and:
    445	  integer_bitor
    446	| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
    447	;
    448
    449integer_bitor:
    450	  integer_bitxor
    451	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
    452	;
    453
    454integer_bitxor:
    455	  integer_bitand
    456	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
    457	;
    458
    459integer_bitand:
    460	  integer_eq
    461	| integer_bitand '&' integer_eq { $$ = $1 & $3; }
    462	;
    463
    464integer_eq:
    465	  integer_rela
    466	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
    467	| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
    468	;
    469
    470integer_rela:
    471	  integer_shift
    472	| integer_rela '<' integer_shift { $$ = $1 < $3; }
    473	| integer_rela '>' integer_shift { $$ = $1 > $3; }
    474	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
    475	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
    476	;
    477
    478integer_shift:
    479	  integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
    480	| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
    481	| integer_add
    482	;
    483
    484integer_add:
    485	  integer_add '+' integer_mul { $$ = $1 + $3; }
    486	| integer_add '-' integer_mul { $$ = $1 - $3; }
    487	| integer_mul
    488	;
    489
    490integer_mul:
    491	  integer_mul '*' integer_unary { $$ = $1 * $3; }
    492	| integer_mul '/' integer_unary
    493		{
    494			if ($3 != 0) {
    495				$$ = $1 / $3;
    496			} else {
    497				ERROR(&@$, "Division by zero");
    498				$$ = 0;
    499			}
    500		}
    501	| integer_mul '%' integer_unary
    502		{
    503			if ($3 != 0) {
    504				$$ = $1 % $3;
    505			} else {
    506				ERROR(&@$, "Division by zero");
    507				$$ = 0;
    508			}
    509		}
    510	| integer_unary
    511	;
    512
    513integer_unary:
    514	  integer_prim
    515	| '-' integer_unary { $$ = -$2; }
    516	| '~' integer_unary { $$ = ~$2; }
    517	| '!' integer_unary { $$ = !$2; }
    518	;
    519
    520bytestring:
    521	  /* empty */
    522		{
    523			$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
    524		}
    525	| bytestring DT_BYTE
    526		{
    527			$$ = data_append_byte($1, $2);
    528		}
    529	| bytestring DT_LABEL
    530		{
    531			$$ = data_add_marker($1, LABEL, $2);
    532		}
    533	;
    534
    535subnodes:
    536	  /* empty */
    537		{
    538			$$ = NULL;
    539		}
    540	| subnode subnodes
    541		{
    542			$$ = chain_node($1, $2);
    543		}
    544	| subnode propdef
    545		{
    546			ERROR(&@2, "Properties must precede subnodes");
    547			YYERROR;
    548		}
    549	;
    550
    551subnode:
    552	  DT_PROPNODENAME nodedef
    553		{
    554			$$ = name_node($2, $1);
    555		}
    556	| DT_DEL_NODE DT_PROPNODENAME ';'
    557		{
    558			$$ = name_node(build_node_delete(&@$), $2);
    559		}
    560	| DT_OMIT_NO_REF subnode
    561		{
    562			$$ = omit_node_if_unused($2);
    563		}
    564	| DT_LABEL subnode
    565		{
    566			add_label(&$2->labels, $1);
    567			$$ = $2;
    568		}
    569	;
    570
    571%%
    572
    573void yyerror(char const *s)
    574{
    575	ERROR(&yylloc, "%s", s);
    576}