Skip to content

Commit 401d137

Browse files
author
Phil Elwell
committed
scripts/dtc: Add overlay support
1 parent ff73286 commit 401d137

File tree

7 files changed

+325
-12
lines changed

7 files changed

+325
-12
lines changed

scripts/dtc/checks.c

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -458,21 +458,91 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
458458
struct node *node, struct property *prop)
459459
{
460460
struct marker *m = prop->val.markers;
461+
struct fixup *f, **fp;
462+
struct fixup_entry *fe, **fep;
461463
struct node *refnode;
462464
cell_t phandle;
465+
int has_phandle_refs;
466+
467+
has_phandle_refs = 0;
468+
for_each_marker_of_type(m, REF_PHANDLE) {
469+
has_phandle_refs = 1;
470+
break;
471+
}
472+
473+
if (!has_phandle_refs)
474+
return;
463475

464476
for_each_marker_of_type(m, REF_PHANDLE) {
465477
assert(m->offset + sizeof(cell_t) <= prop->val.len);
466478

467479
refnode = get_node_by_ref(dt, m->ref);
468-
if (! refnode) {
480+
if (!refnode && !symbol_fixup_support) {
469481
FAIL(c, "Reference to non-existent node or label \"%s\"\n",
470-
m->ref);
482+
m->ref);
471483
continue;
472484
}
473485

474-
phandle = get_node_phandle(dt, refnode);
475-
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
486+
if (!refnode) {
487+
/* allocate fixup entry */
488+
fe = xmalloc(sizeof(*fe));
489+
490+
fe->node = node;
491+
fe->prop = prop;
492+
fe->offset = m->offset;
493+
fe->next = NULL;
494+
495+
/* search for an already existing fixup */
496+
for_each_fixup(dt, f)
497+
if (strcmp(f->ref, m->ref) == 0)
498+
break;
499+
500+
/* no fixup found, add new */
501+
if (f == NULL) {
502+
f = xmalloc(sizeof(*f));
503+
f->ref = m->ref;
504+
f->entries = NULL;
505+
f->next = NULL;
506+
507+
/* add it to the tree */
508+
fp = &dt->fixups;
509+
while (*fp)
510+
fp = &(*fp)->next;
511+
*fp = f;
512+
}
513+
514+
/* and now append fixup entry */
515+
fep = &f->entries;
516+
while (*fep)
517+
fep = &(*fep)->next;
518+
*fep = fe;
519+
520+
/* mark the entry as unresolved */
521+
phandle = 0xdeadbeef;
522+
} else {
523+
phandle = get_node_phandle(dt, refnode);
524+
525+
/* if it's a plugin, we need to record it */
526+
if (symbol_fixup_support && dt->is_plugin) {
527+
528+
/* allocate a new local fixup entry */
529+
fe = xmalloc(sizeof(*fe));
530+
531+
fe->node = node;
532+
fe->prop = prop;
533+
fe->offset = m->offset;
534+
fe->next = NULL;
535+
536+
/* append it to the local fixups */
537+
fep = &dt->local_fixups;
538+
while (*fep)
539+
fep = &(*fep)->next;
540+
*fep = fe;
541+
}
542+
}
543+
544+
*((cell_t *)(prop->val.val + m->offset)) =
545+
cpu_to_fdt32(phandle);
476546
}
477547
}
478548
ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
@@ -652,6 +722,45 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
652722
}
653723
TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
654724

725+
static void check_auto_label_phandles(struct check *c, struct node *dt,
726+
struct node *node)
727+
{
728+
struct label *l;
729+
struct symbol *s, **sp;
730+
int has_label;
731+
732+
if (!symbol_fixup_support)
733+
return;
734+
735+
has_label = 0;
736+
for_each_label(node->labels, l) {
737+
has_label = 1;
738+
break;
739+
}
740+
741+
if (!has_label)
742+
return;
743+
744+
/* force allocation of a phandle for this node */
745+
(void)get_node_phandle(dt, node);
746+
747+
/* add the symbol */
748+
for_each_label(node->labels, l) {
749+
750+
s = xmalloc(sizeof(*s));
751+
s->label = l;
752+
s->node = node;
753+
s->next = NULL;
754+
755+
/* add it to the symbols list */
756+
sp = &dt->symbols;
757+
while (*sp)
758+
sp = &((*sp)->next);
759+
*sp = s;
760+
}
761+
}
762+
NODE_WARNING(auto_label_phandles, NULL);
763+
655764
static struct check *check_table[] = {
656765
&duplicate_node_names, &duplicate_property_names,
657766
&node_name_chars, &node_name_format, &property_name_chars,
@@ -670,6 +779,8 @@ static struct check *check_table[] = {
670779
&avoid_default_addr_size,
671780
&obsolete_chosen_interrupt_controller,
672781

782+
&auto_label_phandles,
783+
673784
&always_fail,
674785
};
675786

scripts/dtc/dtc-lexer.l

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ static void lexical_error(const char *fmt, ...);
113113
return DT_V1;
114114
}
115115

116+
<*>"/plugin/" {
117+
DPRINT("Keyword: /plugin/\n");
118+
return DT_PLUGIN;
119+
}
120+
116121
<*>"/memreserve/" {
117122
DPRINT("Keyword: /memreserve/\n");
118123
BEGIN_DEFAULT();

scripts/dtc/dtc-parser.y

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020
%{
2121
#include <stdio.h>
22+
#include <inttypes.h>
2223

2324
#include "dtc.h"
2425
#include "srcpos.h"
@@ -52,9 +53,11 @@ extern bool treesource_error;
5253
struct node *nodelist;
5354
struct reserve_info *re;
5455
uint64_t integer;
56+
int is_plugin;
5557
}
5658

5759
%token DT_V1
60+
%token DT_PLUGIN
5861
%token DT_MEMRESERVE
5962
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
6063
%token DT_BITS
@@ -71,6 +74,7 @@ extern bool treesource_error;
7174

7275
%type <data> propdata
7376
%type <data> propdataprefix
77+
%type <is_plugin> plugindecl
7478
%type <re> memreserve
7579
%type <re> memreserves
7680
%type <array> arrayprefix
@@ -101,10 +105,23 @@ extern bool treesource_error;
101105
%%
102106

103107
sourcefile:
104-
DT_V1 ';' memreserves devicetree
108+
DT_V1 ';' plugindecl memreserves devicetree
105109
{
106-
the_boot_info = build_boot_info($3, $4,
107-
guess_boot_cpuid($4));
110+
$5->is_plugin = $3;
111+
$5->is_root = 1;
112+
the_boot_info = build_boot_info($4, $5,
113+
guess_boot_cpuid($5));
114+
}
115+
;
116+
117+
plugindecl:
118+
/* empty */
119+
{
120+
$$ = 0;
121+
}
122+
| DT_PLUGIN ';'
123+
{
124+
$$ = 1;
108125
}
109126
;
110127

scripts/dtc/dtc.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ int reservenum; /* Number of memory reservation slots */
2929
int minsize; /* Minimum blob size */
3030
int padsize; /* Additional padding to blob */
3131
int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
32+
int symbol_fixup_support = 0;
3233

3334
static void fill_fullpaths(struct node *tree, const char *prefix)
3435
{
@@ -51,7 +52,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
5152
#define FDT_VERSION(version) _FDT_VERSION(version)
5253
#define _FDT_VERSION(version) #version
5354
static const char usage_synopsis[] = "dtc [options] <input file>";
54-
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
55+
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv@";
5556
static struct option const usage_long_opts[] = {
5657
{"quiet", no_argument, NULL, 'q'},
5758
{"in-format", a_argument, NULL, 'I'},
@@ -69,6 +70,7 @@ static struct option const usage_long_opts[] = {
6970
{"phandle", a_argument, NULL, 'H'},
7071
{"warning", a_argument, NULL, 'W'},
7172
{"error", a_argument, NULL, 'E'},
73+
{"symbols", a_argument, NULL, '@'},
7274
{"help", no_argument, NULL, 'h'},
7375
{"version", no_argument, NULL, 'v'},
7476
{NULL, no_argument, NULL, 0x0},
@@ -99,6 +101,7 @@ static const char * const usage_opts_help[] = {
99101
"\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
100102
"\n\tEnable/disable warnings (prefix with \"no-\")",
101103
"\n\tEnable/disable errors (prefix with \"no-\")",
104+
"\n\tSymbols and Fixups support",
102105
"\n\tPrint this help and exit",
103106
"\n\tPrint version and exit",
104107
NULL,
@@ -186,7 +189,9 @@ int main(int argc, char *argv[])
186189
case 'E':
187190
parse_checks_option(false, true, optarg);
188191
break;
189-
192+
case '@':
193+
symbol_fixup_support = 1;
194+
break;
190195
case 'h':
191196
usage(NULL);
192197
default:

scripts/dtc/dtc.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ extern int reservenum; /* Number of memory reservation slots */
5454
extern int minsize; /* Minimum blob size */
5555
extern int padsize; /* Additional padding to blob */
5656
extern int phandle_format; /* Use linux,phandle or phandle properties */
57+
extern int symbol_fixup_support;/* enable symbols & fixup support */
5758

5859
#define PHANDLE_LEGACY 0x1
5960
#define PHANDLE_EPAPR 0x2
@@ -132,6 +133,25 @@ struct label {
132133
struct label *next;
133134
};
134135

136+
struct fixup_entry {
137+
int offset;
138+
struct node *node;
139+
struct property *prop;
140+
struct fixup_entry *next;
141+
};
142+
143+
struct fixup {
144+
char *ref;
145+
struct fixup_entry *entries;
146+
struct fixup *next;
147+
};
148+
149+
struct symbol {
150+
struct label *label;
151+
struct node *node;
152+
struct symbol *next;
153+
};
154+
135155
struct property {
136156
bool deleted;
137157
char *name;
@@ -158,6 +178,12 @@ struct node {
158178
int addr_cells, size_cells;
159179

160180
struct label *labels;
181+
182+
int is_root;
183+
int is_plugin;
184+
struct fixup *fixups;
185+
struct symbol *symbols;
186+
struct fixup_entry *local_fixups;
161187
};
162188

163189
#define for_each_label_withdel(l0, l) \
@@ -181,6 +207,18 @@ struct node {
181207
for_each_child_withdel(n, c) \
182208
if (!(c)->deleted)
183209

210+
#define for_each_fixup(n, f) \
211+
for ((f) = (n)->fixups; (f); (f) = (f)->next)
212+
213+
#define for_each_fixup_entry(f, fe) \
214+
for ((fe) = (f)->entries; (fe); (fe) = (fe)->next)
215+
216+
#define for_each_symbol(n, s) \
217+
for ((s) = (n)->symbols; (s); (s) = (s)->next)
218+
219+
#define for_each_local_fixup_entry(n, fe) \
220+
for ((fe) = (n)->local_fixups; (fe); (fe) = (fe)->next)
221+
184222
void add_label(struct label **labels, char *label);
185223
void delete_labels(struct label **labels);
186224

0 commit comments

Comments
 (0)