diff options
Diffstat (limited to 'scripts/dtc/dtc-parser.y')
-rw-r--r-- | scripts/dtc/dtc-parser.y | 91 |
1 files changed, 82 insertions, 9 deletions
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index ea57e0a056..44af170abf 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -19,6 +19,7 @@ */ %{ #include <stdio.h> +#include <inttypes.h> #include "dtc.h" #include "srcpos.h" @@ -31,7 +32,7 @@ extern void yyerror(char const *s); treesource_error = true; \ } while (0) -extern struct boot_info *the_boot_info; +extern struct dt_info *parser_output; extern bool treesource_error; %} @@ -52,9 +53,11 @@ extern bool treesource_error; struct node *nodelist; struct reserve_info *re; uint64_t integer; + unsigned int flags; } %token DT_V1 +%token DT_PLUGIN %token DT_MEMRESERVE %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR %token DT_BITS @@ -71,6 +74,8 @@ extern bool treesource_error; %type <data> propdata %type <data> propdataprefix +%type <flags> header +%type <flags> headers %type <re> memreserve %type <re> memreserves %type <array> arrayprefix @@ -101,10 +106,31 @@ extern bool treesource_error; %% sourcefile: - DT_V1 ';' memreserves devicetree + headers memreserves devicetree { - the_boot_info = build_boot_info($3, $4, - guess_boot_cpuid($4)); + parser_output = build_dt_info($1, $2, $3, + guess_boot_cpuid($3)); + } + ; + +header: + DT_V1 ';' + { + $$ = DTSF_V1; + } + | DT_V1 ';' DT_PLUGIN ';' + { + $$ = DTSF_V1 | DTSF_PLUGIN; + } + ; + +headers: + header + | header headers + { + if ($2 != $1) + ERROR(&@2, "Header flags don't match earlier ones"); + $$ = $1; } ; @@ -140,14 +166,45 @@ devicetree: { $$ = merge_nodes($1, $3); } + | DT_REF nodedef + { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if (!($<flags>-1 & DTSF_PLUGIN)) + ERROR(&@2, "Label or path %s not found", $1); + $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); + } + | devicetree DT_LABEL DT_REF nodedef + { + struct node *target = get_node_by_ref($1, $3); + + if (target) { + add_label(&target->labels, $2); + merge_nodes(target, $4); + } else + ERROR(&@3, "Label or path %s not found", $3); + $$ = $1; + } | devicetree DT_REF nodedef { struct node *target = get_node_by_ref($1, $2); - if (target) + if (target) { merge_nodes(target, $3); - else - ERROR(&@2, "Label or path %s not found", $2); + } else { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ($<flags>-1 & DTSF_PLUGIN) + add_orphan_node($1, $3, $2); + else + ERROR(&@2, "Label or path %s not found", $2); + } $$ = $1; } | devicetree DT_DEL_NODE DT_REF ';' @@ -398,8 +455,24 @@ integer_add: integer_mul: integer_mul '*' integer_unary { $$ = $1 * $3; } - | integer_mul '/' integer_unary { $$ = $1 / $3; } - | integer_mul '%' integer_unary { $$ = $1 % $3; } + | integer_mul '/' integer_unary + { + if ($3 != 0) { + $$ = $1 / $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } + | integer_mul '%' integer_unary + { + if ($3 != 0) { + $$ = $1 % $3; + } else { + ERROR(&@$, "Division by zero"); + $$ = 0; + } + } | integer_unary ; |