dc941774e2
Currently, every 'data' object, used to represent property values, has two lists of fixup structures - one for labels and one for references. Sometimes we want to look at them separately, but other times we need to consider both types of fixup. I'm planning to implement string references, where a full path rather than a phandle is substituted into a property value. Adding yet another list of fixups for that would start to get silly. So, this patch merges the "refs" and "labels" lists into a single list of "markers", each of which has a type field indicating if it represents a label or a phandle reference. String references or any other new type of in-data marker will then just need a new type value - merging data blocks and other common manipulations will just work. While I was at it I made some cleanups to the handling of fixups which simplify things further. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
327 lines
5.2 KiB
Text
327 lines
5.2 KiB
Text
/*
|
|
* (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 "dtc.h"
|
|
#include "srcpos.h"
|
|
|
|
int yylex(void);
|
|
unsigned long long eval_literal(const char *s, int base, int bits);
|
|
|
|
extern struct boot_info *the_boot_info;
|
|
|
|
%}
|
|
|
|
%union {
|
|
char *propnodename;
|
|
char *literal;
|
|
char *labelref;
|
|
unsigned int cbase;
|
|
u8 byte;
|
|
struct data data;
|
|
|
|
u64 addr;
|
|
cell_t cell;
|
|
struct property *prop;
|
|
struct property *proplist;
|
|
struct node *node;
|
|
struct node *nodelist;
|
|
struct reserve_info *re;
|
|
}
|
|
|
|
%token DT_V1
|
|
%token DT_MEMRESERVE
|
|
%token <propnodename> DT_PROPNODENAME
|
|
%token <literal> DT_LITERAL
|
|
%token <literal> DT_LEGACYLITERAL
|
|
%token <cbase> DT_BASE
|
|
%token <byte> DT_BYTE
|
|
%token <data> DT_STRING
|
|
%token <labelref> DT_LABEL
|
|
%token <labelref> DT_REF
|
|
|
|
%type <data> propdata
|
|
%type <data> propdataprefix
|
|
%type <re> memreserve
|
|
%type <re> memreserves
|
|
%type <re> v0_memreserve
|
|
%type <re> v0_memreserves
|
|
%type <addr> addr
|
|
%type <data> celllist
|
|
%type <cbase> cellbase
|
|
%type <cell> cellval
|
|
%type <data> bytestring
|
|
%type <prop> propdef
|
|
%type <proplist> proplist
|
|
|
|
%type <node> devicetree
|
|
%type <node> nodedef
|
|
%type <node> subnode
|
|
%type <nodelist> subnodes
|
|
%type <labelref> label
|
|
|
|
%%
|
|
|
|
sourcefile:
|
|
DT_V1 ';' memreserves devicetree
|
|
{
|
|
the_boot_info = build_boot_info($3, $4);
|
|
}
|
|
| v0_memreserves devicetree
|
|
{
|
|
the_boot_info = build_boot_info($1, $2);
|
|
}
|
|
;
|
|
|
|
memreserves:
|
|
/* empty */
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
| memreserve memreserves
|
|
{
|
|
$$ = chain_reserve_entry($1, $2);
|
|
}
|
|
;
|
|
|
|
memreserve:
|
|
label DT_MEMRESERVE addr addr ';'
|
|
{
|
|
$$ = build_reserve_entry($3, $4, $1);
|
|
}
|
|
;
|
|
|
|
v0_memreserves:
|
|
/* empty */
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
| v0_memreserve v0_memreserves
|
|
{
|
|
$$ = chain_reserve_entry($1, $2);
|
|
};
|
|
;
|
|
|
|
v0_memreserve:
|
|
memreserve
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| label DT_MEMRESERVE addr '-' addr ';'
|
|
{
|
|
$$ = build_reserve_entry($3, $5 - $3 + 1, $1);
|
|
}
|
|
;
|
|
|
|
addr:
|
|
DT_LITERAL
|
|
{
|
|
$$ = eval_literal($1, 0, 64);
|
|
}
|
|
| DT_LEGACYLITERAL
|
|
{
|
|
$$ = eval_literal($1, 16, 64);
|
|
}
|
|
;
|
|
|
|
devicetree:
|
|
'/' nodedef
|
|
{
|
|
$$ = name_node($2, "", NULL);
|
|
}
|
|
;
|
|
|
|
nodedef:
|
|
'{' proplist subnodes '}' ';'
|
|
{
|
|
$$ = build_node($2, $3);
|
|
}
|
|
;
|
|
|
|
proplist:
|
|
/* empty */
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
| proplist propdef
|
|
{
|
|
$$ = chain_property($2, $1);
|
|
}
|
|
;
|
|
|
|
propdef:
|
|
label DT_PROPNODENAME '=' propdata ';'
|
|
{
|
|
$$ = build_property($2, $4, $1);
|
|
}
|
|
| label DT_PROPNODENAME ';'
|
|
{
|
|
$$ = build_property($2, empty_data, $1);
|
|
}
|
|
;
|
|
|
|
propdata:
|
|
propdataprefix DT_STRING
|
|
{
|
|
$$ = data_merge($1, $2);
|
|
}
|
|
| propdataprefix '<' celllist '>'
|
|
{
|
|
$$ = data_merge($1, $3);
|
|
}
|
|
| propdataprefix '[' bytestring ']'
|
|
{
|
|
$$ = data_merge($1, $3);
|
|
}
|
|
| propdata DT_LABEL
|
|
{
|
|
$$ = data_add_marker($1, LABEL, $2);
|
|
}
|
|
;
|
|
|
|
propdataprefix:
|
|
/* empty */
|
|
{
|
|
$$ = empty_data;
|
|
}
|
|
| propdata ','
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| propdataprefix DT_LABEL
|
|
{
|
|
$$ = data_add_marker($1, LABEL, $2);
|
|
}
|
|
;
|
|
|
|
celllist:
|
|
/* empty */
|
|
{
|
|
$$ = empty_data;
|
|
}
|
|
| celllist cellval
|
|
{
|
|
$$ = data_append_cell($1, $2);
|
|
}
|
|
| celllist DT_REF
|
|
{
|
|
$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
|
|
$2), -1);
|
|
}
|
|
| celllist DT_LABEL
|
|
{
|
|
$$ = data_add_marker($1, LABEL, $2);
|
|
}
|
|
;
|
|
|
|
cellbase:
|
|
/* empty */
|
|
{
|
|
$$ = 16;
|
|
}
|
|
| DT_BASE
|
|
;
|
|
|
|
cellval:
|
|
DT_LITERAL
|
|
{
|
|
$$ = eval_literal($1, 0, 32);
|
|
}
|
|
| cellbase DT_LEGACYLITERAL
|
|
{
|
|
$$ = eval_literal($2, $1, 32);
|
|
}
|
|
;
|
|
|
|
bytestring:
|
|
/* empty */
|
|
{
|
|
$$ = empty_data;
|
|
}
|
|
| bytestring DT_BYTE
|
|
{
|
|
$$ = data_append_byte($1, $2);
|
|
}
|
|
| bytestring DT_LABEL
|
|
{
|
|
$$ = data_add_marker($1, LABEL, $2);
|
|
}
|
|
;
|
|
|
|
subnodes:
|
|
/* empty */
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
| subnode subnodes
|
|
{
|
|
$$ = chain_node($1, $2);
|
|
}
|
|
;
|
|
|
|
subnode:
|
|
label DT_PROPNODENAME nodedef
|
|
{
|
|
$$ = name_node($3, $2, $1);
|
|
}
|
|
;
|
|
|
|
label:
|
|
/* empty */
|
|
{
|
|
$$ = NULL;
|
|
}
|
|
| DT_LABEL
|
|
{
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
%%
|
|
|
|
void yyerror (char const *s)
|
|
{
|
|
const char *fname = srcpos_filename_for_num(yylloc.filenum);
|
|
|
|
if (strcmp(fname, "-") == 0)
|
|
fname = "stdin";
|
|
|
|
fprintf(stderr, "%s:%d %s\n",
|
|
fname, yylloc.first_line, s);
|
|
}
|
|
|
|
unsigned long long eval_literal(const char *s, int base, int bits)
|
|
{
|
|
unsigned long long val;
|
|
char *e;
|
|
|
|
errno = 0;
|
|
val = strtoull(s, &e, base);
|
|
if (*e)
|
|
yyerror("bad characters in literal");
|
|
else if ((errno == ERANGE)
|
|
|| ((bits < 64) && (val >= (1ULL << bits))))
|
|
yyerror("literal out of range");
|
|
else if (errno != 0)
|
|
yyerror("bad literal");
|
|
return val;
|
|
}
|