Browse Source

Rudimentary phandle reference support.

main
David Gibson 20 years ago
parent
commit
81f2e89c75
  1. 34
      data.c
  2. 62
      dtc-lexer.l
  3. 4
      dtc-parser.y
  4. 15
      dtc.h
  5. 2
      flattree.c
  6. 97
      livetree.c
  7. 11
      test.dts

34
data.c

@ -38,8 +38,25 @@ struct data data_ref_string(char *str) @@ -38,8 +38,25 @@ struct data data_ref_string(char *str)
}
#endif

void fixup_free(struct fixup *f)
{
free(f->ref);
free(f);
}

void data_free(struct data d)
{
struct fixup *f;

f = d.refs;
while (f) {
struct fixup *nf;

nf = f->next;
fixup_free(f);
f = nf;
}

assert(!d.val || d.asize);

if (d.val)
@ -65,6 +82,7 @@ struct data data_grow_for(struct data d, int xlen) @@ -65,6 +82,7 @@ struct data data_grow_for(struct data d, int xlen)
nd.asize = newsize;
nd.val = xrealloc(d.val, newsize);
nd.len = d.len;
nd.refs = d.refs;

assert(nd.asize >= (d.len + xlen));

@ -231,6 +249,22 @@ struct data data_append_align(struct data d, int align) @@ -231,6 +249,22 @@ struct data data_append_align(struct data d, int align)
return data_append_zeroes(d, newlen - d.len);
}

struct data data_add_fixup(struct data d, char *ref)
{
struct fixup *f;
struct data nd;

f = xmalloc(sizeof(*f));
f->offset = d.len;
f->ref = ref;
f->next = d.refs;

nd = d;
nd.refs = f;

return nd;
}

int data_is_one_string(struct data d)
{
int i;

62
dtc-lexer.l

@ -27,6 +27,8 @@ PROPCHAR [a-zA-Z0-9,._+*#?-] @@ -27,6 +27,8 @@ PROPCHAR [a-zA-Z0-9,._+*#?-]
UNITCHAR [0-9a-f,]
WS [ \t\n]

REFCHAR ({PROPCHAR}|{UNITCHAR}|[/@])

%%

%{
@ -36,12 +38,16 @@ WS [ \t\n] @@ -36,12 +38,16 @@ WS [ \t\n]

/*#define LEXDEBUG 1*/

#ifdef LEXDEBUG
#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#else
#define DPRINT(fmt, ...) do { } while (0)
#endif

%}

\"[^"]*\" {
#ifdef LEXDEBUG
fprintf(stderr, "String: %s\n", yytext);
#endif
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
yyleng-2);
return DT_STRING;
@ -53,57 +59,49 @@ WS [ \t\n] @@ -53,57 +59,49 @@ WS [ \t\n]
"Cell value %s too long\n", yytext);
}
yylval.cval = strtol(yytext, NULL, 16);
#ifdef LEXDEBUG
fprintf(stderr, "Cell: %x\n", yylval.cval);
#endif
DPRINT("Cell: %x\n", yylval.cval);
return DT_CELL;
}

<CELLDATA>">" {
#ifdef LEXDEBUG
fprintf(stderr, "/CELLDATA\n");
#endif
DPRINT("/CELLDATA\n");
BEGIN(INITIAL);
return '>';
}

<CELLDATA>\&{REFCHAR}* {
DPRINT("Ref: %s\n", yytext+1);
yylval.str = strdup(yytext+1);
return DT_REF;
}

<BYTESTRING>[0-9a-fA-F]{2} {
yylval.byte = strtol(yytext, NULL, 16);
#ifdef LEXDEBUG
fprintf(stderr, "Byte: %02x\n", (int)yylval.byte);
#endif
DPRINT("Byte: %02x\n", (int)yylval.byte);
return DT_BYTE;
}

<BYTESTRING>"]" {
#ifdef LEXDEBUG
fprintf(stderr, "/BYTESTRING\n");
#endif
DPRINT("/BYTESTRING\n");
BEGIN(INITIAL);
return ']';
}

{PROPCHAR}+ {
#ifdef LEXDEBUG
fprintf(stderr, "PropName: %s\n", yytext);
#endif
DPRINT("PropName: %s\n", yytext);
yylval.str = strdup(yytext);
return DT_PROPNAME;
}

{PROPCHAR}+(@{UNITCHAR}+)? {
#ifdef LEXDEBUG
fprintf(stderr, "NodeName: %s\n", yytext);
#endif
DPRINT("NodeName: %s\n", yytext);
yylval.str = strdup(yytext);
return DT_NODENAME;
}


[a-zA-Z_][a-zA-Z0-9_]*: {
#ifdef LEXDEBUG
fprintf(stderr, "Label: %s\n", yytext);
#endif
DPRINT("Label: %s\n", yytext);
yylval.str = strdup(yytext);
yylval.str[yyleng-1] = '\0';
return DT_LABEL;
@ -112,10 +110,8 @@ WS [ \t\n] @@ -112,10 +110,8 @@ WS [ \t\n]
<*>{WS}+ /* eat whitespace */

<*>"/*"([^*]|\*+[^*/])*\*+"/" {
#ifdef LEXDEBUG
fprintf(stderr, "Comment: %s\n", yytext);
DPRINT("Comment: %s\n", yytext);
/* eat comments */
#endif
}

<*>"//".*\n /* eat line comments */
@ -123,23 +119,17 @@ WS [ \t\n] @@ -123,23 +119,17 @@ WS [ \t\n]
. {
switch (yytext[0]) {
case '<':
#ifdef LEXDEBUG
fprintf(stderr, "CELLDATA\n");
#endif
DPRINT("CELLDATA\n");
BEGIN(CELLDATA);
break;
case '[':
#ifdef LEXDEBUG
fprintf(stderr, "BYTESTRING\n");
#endif
DPRINT("BYTESTRING\n");
BEGIN(BYTESTRING);
break;
default:

#ifdef LEXDEBUG
fprintf(stderr, "Char: %c (\\x%02x)\n", yytext[0],
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
#endif
break;
}


4
dtc-parser.y

@ -48,6 +48,7 @@ extern struct node *device_tree; @@ -48,6 +48,7 @@ extern struct node *device_tree;
%token <data> DT_STRING
%token <str> DT_UNIT
%token <str> DT_LABEL
%token <str> DT_REF

%type <data> propdata
%type <data> celllist
@ -97,6 +98,9 @@ propdata: DT_STRING { $$ = $1; } @@ -97,6 +98,9 @@ propdata: DT_STRING { $$ = $1; }
;

celllist: celllist DT_CELL { $$ = data_append_cell($1, $2); }
| celllist DT_REF {
$$ = data_append_cell(data_add_fixup($1, $2), -1);
}
| /* empty */ { $$ = empty_data; }
;


15
dtc.h

@ -76,18 +76,29 @@ typedef u32 cell_t; @@ -76,18 +76,29 @@ typedef u32 cell_t;


#define streq(a, b) (strcmp((a), (b)) == 0)
#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)

#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

/* Data blobs */
struct fixup {
int offset;
char *ref;
struct fixup *next;
};

struct data {
int len;
char *val;
int asize;
struct fixup *refs;
};

#define empty_data ((struct data){.len = 0, .val = NULL, .asize = 0})
#define empty_data \
((struct data){.len = 0, .val = NULL, .asize = 0, .refs = NULL})

void fixup_free(struct fixup *f);
void data_free(struct data d);

struct data data_grow_for(struct data d, int xlen);
@ -102,6 +113,8 @@ struct data data_append_byte(struct data d, uint8_t byte); @@ -102,6 +113,8 @@ struct data data_append_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len);
struct data data_append_align(struct data d, int align);

struct data data_add_fixup(struct data d, char *ref);

int data_is_one_string(struct data d);

/* DT constraints */

2
flattree.c

@ -598,7 +598,7 @@ static char *nodename_from_path(char *ppath, char *cpath) @@ -598,7 +598,7 @@ static char *nodename_from_path(char *ppath, char *cpath)
if ((plen == 0) && streq(ppath, "/"))
return strdup(lslash+1);

if (strncmp(ppath, cpath, plen) != 0)
if (! strneq(ppath, cpath, plen))
return NULL;
return strdup(lslash+1);

97
livetree.c

@ -43,9 +43,7 @@ struct property *build_empty_property(char *name, char *label) @@ -43,9 +43,7 @@ struct property *build_empty_property(char *name, char *label)
struct property *new = xmalloc(sizeof(*new));

new->name = name;
new->val.len = 0;
new->val.val = NULL;

new->val = empty_data;
new->next = NULL;

new->label = label;
@ -141,8 +139,30 @@ static struct node *get_subnode(struct node *node, char *nodename) @@ -141,8 +139,30 @@ static struct node *get_subnode(struct node *node, char *nodename)
{
struct node *child;

for_each_child(node, child) {
if (strcmp(child->name, nodename) == 0)
for_each_child(node, child)
if (streq(child->name, nodename))
return child;

return NULL;
}

static struct node *get_node_by_path(struct node *tree, char *path)
{
char *p;
struct node *child;

if (!path || ! (*path))
return tree;

while (path[0] == '/')
path++;

p = strchr(path, '/');

for_each_child(tree, child) {
if (p && strneq(path, child->name, p-path))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
}

@ -209,7 +229,7 @@ static int must_be_string(struct property *prop, struct node *node) @@ -209,7 +229,7 @@ static int must_be_string(struct property *prop, struct node *node)
static int name_prop_check(struct property *prop, struct node *node)
{
if ((prop->val.len != node->basenamelen+1)
|| (strncmp(prop->val.val, node->name, node->basenamelen) != 0)) {
|| !strneq(prop->val.val, node->name, node->basenamelen)) {
ERRMSG("name property \"%s\" does not match node basename in %s\n",
prop->val.val,
node->fullpath);
@ -469,7 +489,7 @@ static int check_memory(struct node *root) @@ -469,7 +489,7 @@ static int check_memory(struct node *root)
int ok = 1;

for_each_child(root, mem) {
if (strncmp(mem->name, "memory", mem->basenamelen) != 0)
if (! strneq(mem->name, "memory", mem->basenamelen))
continue;

nnodes++;
@ -573,6 +593,67 @@ static int check_phandles(struct node *root, struct node *node) @@ -573,6 +593,67 @@ static int check_phandles(struct node *root, struct node *node)
return 1;
}

static cell_t get_node_phandle(struct node *root, struct node *node)
{
static cell_t phandle = 1; /* FIXME: ick, static local */

fprintf(stderr, "get_node_phandle(%s) phandle=%x\n",
node->fullpath, node->phandle);

if ((node->phandle != 0) && (node->phandle != -1))
return node->phandle;

assert(! get_property(node, "linux,phandle"));

while (get_node_by_phandle(root, phandle))
phandle++;

node->phandle = phandle;
add_property(node,
build_property("linux,phandle",
data_append_cell(empty_data, phandle),
NULL));

return node->phandle;
}

static void apply_fixup(struct node *root, struct property *prop,
struct fixup *f)
{
struct node *refnode;
cell_t phandle;

refnode = get_node_by_path(root, f->ref);
if (! refnode)
die("Reference to non-existent node \"%s\"\n", f->ref);

phandle = get_node_phandle(root, refnode);

assert(f->offset + sizeof(cell_t) <= prop->val.len);

*((cell_t *)(prop->val.val + f->offset)) = cpu_to_be32(phandle);
}

static void fixup_phandles(struct node *root, struct node *node)
{
struct property *prop;
struct node *child;

for_each_property(node, prop) {
struct fixup *f = prop->val.refs;

while (f) {
apply_fixup(root, prop, f);
prop->val.refs = f->next;
fixup_free(f);
f = prop->val.refs;
}
}

for_each_child(node, child)
fixup_phandles(root, child);
}

int check_device_tree(struct node *dt)
{
int ok = 1;
@ -583,6 +664,8 @@ int check_device_tree(struct node *dt) @@ -583,6 +664,8 @@ int check_device_tree(struct node *dt)
ok = ok && check_addr_size_reg(dt, -1, -1);
ok = ok && check_phandles(dt, dt);

fixup_phandles(dt, dt);

if (! ok)
return 0;


11
test.dts

@ -2,19 +2,19 @@ @@ -2,19 +2,19 @@
model = "MyBoardName";
compatible = "MyBoardFamilyName";
#address-cells = <2>;
label1: #size-cells = <2>;
#size-cells = <2>;

label2: cpus {
cpus {
linux,phandle = <1>;
#address-cells = <1>;
#size-cells = <0>;
PowerPC,970@0 {
linux,phandle = <3>;
name = "PowerPC,970";
device_type = "cpu";
reg = <0>;
clock-frequency = <5f5e1000>;
linux,boot-cpu;
linux,phandle = <2>;
i-cache-size = <10000>;
d-cache-size = <8000>;
};
@ -24,18 +24,17 @@ @@ -24,18 +24,17 @@
randomnode {
string = "\xff\0stuffstuff\t\t\t\n\n\n";
blob = [0a 0b 0c 0d de ea ad be ef];
ref = < &/memory@0 >;
};

memory@0 {
device_type = "memory";
reg = <00000000 00000000 00000000 20000000>;
linux,phandle = <3>;
memreg: reg = <00000000 00000000 00000000 20000000>;
};

chosen {
bootargs = "root=/dev/sda2";
linux,platform = <00000600>;
linux,phandle = <4>;
};

};

Loading…
Cancel
Save