diff options
Diffstat (limited to 'scripts/dtc/dtc-parser.y')
-rw-r--r-- | scripts/dtc/dtc-parser.y | 93 |
1 files changed, 57 insertions, 36 deletions
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 011a5b2553..a0316a3cc3 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. - * - * - * 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 2 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ +%locations + %{ #include <stdio.h> #include <inttypes.h> @@ -32,6 +19,8 @@ extern void yyerror(char const *s); treesource_error = true; \ } while (0) +#define YYERROR_CALL(msg) yyerror(msg) + extern struct dt_info *parser_output; extern bool treesource_error; %} @@ -70,7 +59,8 @@ extern bool treesource_error; %token <byte> DT_BYTE %token <data> DT_STRING %token <labelref> DT_LABEL -%token <labelref> DT_REF +%token <labelref> DT_LABEL_REF +%token <labelref> DT_PATH_REF %token DT_INCBIN %type <data> propdata @@ -83,6 +73,7 @@ extern bool treesource_error; %type <data> bytestring %type <prop> propdef %type <proplist> proplist +%type <labelref> dt_ref %type <node> devicetree %type <node> nodedef @@ -158,6 +149,8 @@ memreserve: } ; +dt_ref: DT_LABEL_REF | DT_PATH_REF; + devicetree: '/' nodedef { @@ -167,7 +160,7 @@ devicetree: { $$ = merge_nodes($1, $3); } - | DT_REF nodedef + | dt_ref nodedef { /* * We rely on the rule being always: @@ -176,9 +169,12 @@ devicetree: */ 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); + $$ = add_orphan_node( + name_node(build_node(NULL, NULL, NULL), + ""), + $2, $1); } - | devicetree DT_LABEL DT_REF nodedef + | devicetree DT_LABEL dt_ref nodedef { struct node *target = get_node_by_ref($1, $3); @@ -189,7 +185,7 @@ devicetree: ERROR(&@3, "Label or path %s not found", $3); $$ = $1; } - | devicetree DT_REF nodedef + | devicetree DT_PATH_REF nodedef { /* * We rely on the rule being always: @@ -208,7 +204,26 @@ devicetree: } $$ = $1; } - | devicetree DT_DEL_NODE DT_REF ';' + | devicetree DT_LABEL_REF nodedef + { + struct node *target = get_node_by_ref($1, $2); + + if (target) { + merge_nodes(target, $3); + } 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 ';' { struct node *target = get_node_by_ref($1, $3); @@ -220,7 +235,7 @@ devicetree: $$ = $1; } - | devicetree DT_OMIT_NO_REF DT_REF ';' + | devicetree DT_OMIT_NO_REF dt_ref ';' { struct node *target = get_node_by_ref($1, $3); @@ -237,7 +252,7 @@ devicetree: nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3); + $$ = build_node($2, $3, &@$); } ; @@ -255,11 +270,11 @@ proplist: propdef: DT_PROPNODENAME '=' propdata ';' { - $$ = build_property($1, $3); + $$ = build_property($1, $3, &@$); } | DT_PROPNODENAME ';' { - $$ = build_property($1, empty_data); + $$ = build_property($1, empty_data, &@$); } | DT_DEL_PROP DT_PROPNODENAME ';' { @@ -285,8 +300,9 @@ propdata: { $$ = data_merge($1, $3); } - | propdataprefix DT_REF + | propdataprefix dt_ref { + $1 = data_add_marker($1, TYPE_STRING, $2); $$ = data_add_marker($1, REF_PATH, $2); } | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' @@ -340,22 +356,27 @@ arrayprefix: DT_BITS DT_LITERAL '<' { unsigned long long bits; + enum markertype type = TYPE_UINT32; bits = $2; - if ((bits != 8) && (bits != 16) && - (bits != 32) && (bits != 64)) { + switch (bits) { + case 8: type = TYPE_UINT8; break; + case 16: type = TYPE_UINT16; break; + case 32: type = TYPE_UINT32; break; + case 64: type = TYPE_UINT64; break; + default: ERROR(&@2, "Array elements must be" " 8, 16, 32 or 64-bits"); bits = 32; } - $$.data = empty_data; + $$.data = data_add_marker(empty_data, type, NULL); $$.bits = bits; } | '<' { - $$.data = empty_data; + $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL); $$.bits = 32; } | arrayprefix integer_prim @@ -377,7 +398,7 @@ arrayprefix: $$.data = data_append_integer($1.data, $2, $1.bits); } - | arrayprefix DT_REF + | arrayprefix dt_ref { uint64_t val = ~0ULL >> (64 - $1.bits); @@ -455,8 +476,8 @@ integer_rela: ; integer_shift: - integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } - | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } + integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; } + | integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; } | integer_add ; @@ -499,7 +520,7 @@ integer_unary: bytestring: /* empty */ { - $$ = empty_data; + $$ = data_add_marker(empty_data, TYPE_UINT8, NULL); } | bytestring DT_BYTE { @@ -534,7 +555,7 @@ subnode: } | DT_DEL_NODE DT_PROPNODENAME ';' { - $$ = name_node(build_node_delete(), $2); + $$ = name_node(build_node_delete(&@$), $2); } | DT_OMIT_NO_REF subnode { |