mirror of
https://github.com/dgibson/dtc.git
synced 2026-05-12 11:43:04 -04:00
Compare commits
9 commits
194ac9422a
...
a26ef6400b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a26ef6400b | ||
|
|
05c524db44 | ||
|
|
db65a3a3f4 | ||
|
|
64330c682c | ||
|
|
cbb48690c6 | ||
|
|
ef3b1baf63 | ||
|
|
7c78c8542d | ||
|
|
14dd76b967 | ||
|
|
9a1c801a1a |
10 changed files with 307 additions and 52 deletions
10
checks.c
10
checks.c
|
|
@ -340,6 +340,14 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
|
|||
}
|
||||
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
|
||||
|
||||
static void check_node_name_not_empty(struct check *c, struct dt_info *dti,
|
||||
struct node *node)
|
||||
{
|
||||
if (node->basenamelen == 0 && node->parent != NULL)
|
||||
FAIL(c, dti, node, "Empty node name");
|
||||
}
|
||||
ERROR(node_name_not_empty, check_node_name_not_empty, NULL, &node_name_chars);
|
||||
|
||||
static void check_node_name_vs_property_name(struct check *c,
|
||||
struct dt_info *dti,
|
||||
struct node *node)
|
||||
|
|
@ -1899,7 +1907,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
|
|||
|
||||
static struct check *check_table[] = {
|
||||
&duplicate_node_names, &duplicate_property_names,
|
||||
&node_name_chars, &node_name_format, &property_name_chars,
|
||||
&node_name_chars, &node_name_format, &node_name_not_empty, &property_name_chars,
|
||||
&name_is_string, &name_properties, &node_name_vs_property_name,
|
||||
|
||||
&duplicate_label,
|
||||
|
|
|
|||
5
dtc.c
5
dtc.c
|
|
@ -338,9 +338,14 @@ int main(int argc, char *argv[])
|
|||
if (auto_label_aliases)
|
||||
generate_label_tree(dti, "aliases", false);
|
||||
|
||||
generate_labels_from_tree(dti, "__symbols__");
|
||||
|
||||
if (generate_symbols)
|
||||
generate_label_tree(dti, "__symbols__", true);
|
||||
|
||||
fixup_phandles(dti, "__fixups__");
|
||||
local_fixup_phandles(dti, "__local_fixups__");
|
||||
|
||||
if (generate_fixups) {
|
||||
generate_fixups_tree(dti, "__fixups__");
|
||||
generate_local_fixups_tree(dti, "__local_fixups__");
|
||||
|
|
|
|||
6
dtc.h
6
dtc.h
|
|
@ -339,9 +339,12 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
|
|||
struct reserve_info *reservelist,
|
||||
struct node *tree, uint32_t boot_cpuid_phys);
|
||||
void sort_tree(struct dt_info *dti);
|
||||
void generate_labels_from_tree(struct dt_info *dti, const char *name);
|
||||
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
|
||||
void generate_fixups_tree(struct dt_info *dti, const char *name);
|
||||
void fixup_phandles(struct dt_info *dti, const char *name);
|
||||
void generate_local_fixups_tree(struct dt_info *dti, const char *name);
|
||||
void local_fixup_phandles(struct dt_info *dti, const char *name);
|
||||
|
||||
/* Checks */
|
||||
|
||||
|
|
@ -357,6 +360,9 @@ struct dt_info *dt_from_blob(const char *fname);
|
|||
|
||||
/* Tree source */
|
||||
|
||||
void property_add_marker(struct property *prop,
|
||||
enum markertype type, unsigned int offset, char *ref);
|
||||
void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset);
|
||||
void dt_to_source(FILE *f, struct dt_info *dti);
|
||||
struct dt_info *dt_from_source(const char *f);
|
||||
|
||||
|
|
|
|||
32
fdtdump.c
32
fdtdump.c
|
|
@ -129,23 +129,25 @@ static void dump_blob(void *blob, bool debug)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (tag != FDT_PROP) {
|
||||
fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag);
|
||||
break;
|
||||
if (tag == FDT_PROP) {
|
||||
sz = fdt32_to_cpu(GET_CELL(p));
|
||||
s = p_strings + fdt32_to_cpu(GET_CELL(p));
|
||||
if (version < 16 && sz >= 8)
|
||||
p = PALIGN(p, 8);
|
||||
t = p;
|
||||
|
||||
p = PALIGN(p + sz, 4);
|
||||
|
||||
dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s);
|
||||
dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off);
|
||||
printf("%*s%s", depth * shift, "", s);
|
||||
utilfdt_print_data(t, sz);
|
||||
printf(";\n");
|
||||
continue;
|
||||
}
|
||||
sz = fdt32_to_cpu(GET_CELL(p));
|
||||
s = p_strings + fdt32_to_cpu(GET_CELL(p));
|
||||
if (version < 16 && sz >= 8)
|
||||
p = PALIGN(p, 8);
|
||||
t = p;
|
||||
|
||||
p = PALIGN(p + sz, 4);
|
||||
|
||||
dumpf("%04"PRIxPTR": string: %s\n", (uintptr_t)s - blob_off, s);
|
||||
dumpf("%04"PRIxPTR": value\n", (uintptr_t)t - blob_off);
|
||||
printf("%*s%s", depth * shift, "", s);
|
||||
utilfdt_print_data(t, sz);
|
||||
printf(";\n");
|
||||
fprintf(stderr, "%*s ** Unknown tag 0x%08"PRIx32"\n", depth * shift, "", tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
8
fdtput.c
8
fdtput.c
|
|
@ -254,19 +254,21 @@ static int create_paths(char **blob, const char *in_path)
|
|||
static int create_node(char **blob, const char *node_name)
|
||||
{
|
||||
int node = 0;
|
||||
char *p;
|
||||
const char *p;
|
||||
char *path = NULL;
|
||||
|
||||
p = strrchr(node_name, '/');
|
||||
if (!p) {
|
||||
report_error(node_name, -1, -FDT_ERR_BADPATH);
|
||||
return -1;
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
*blob = realloc_node(*blob, p + 1);
|
||||
|
||||
if (p > node_name) {
|
||||
node = fdt_path_offset(*blob, node_name);
|
||||
path = xstrndup(node_name, (size_t)(p - node_name));
|
||||
node = fdt_path_offset(*blob, path);
|
||||
free(path);
|
||||
if (node < 0) {
|
||||
report_error(node_name, -1, node);
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -807,6 +807,7 @@ struct dt_info *dt_from_blob(const char *fname)
|
|||
struct node *tree;
|
||||
uint32_t val;
|
||||
int flags = 0;
|
||||
unsigned int dtsflags = DTSF_V1;
|
||||
|
||||
f = srcfile_relative_open(fname, NULL);
|
||||
|
||||
|
|
@ -919,5 +920,8 @@ struct dt_info *dt_from_blob(const char *fname)
|
|||
|
||||
fclose(f);
|
||||
|
||||
return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
|
||||
if (get_subnode(tree, "__fixups__") || get_subnode(tree, "__local_fixups__"))
|
||||
dtsflags |= DTSF_PLUGIN;
|
||||
|
||||
return build_dt_info(dtsflags, reservelist, tree, boot_cpuid_phys);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -407,7 +407,8 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
|||
const char *fixup_str = value;
|
||||
uint32_t path_len, name_len;
|
||||
uint32_t fixup_len;
|
||||
char *sep, *endptr;
|
||||
const char *sep;
|
||||
char *endptr;
|
||||
int poffset, ret;
|
||||
|
||||
fixup_end = memchr(value, '\0', len);
|
||||
|
|
|
|||
174
livetree.c
174
livetree.c
|
|
@ -1112,6 +1112,27 @@ static int generate_local_fixups_tree_internal(struct dt_info *dti,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void generate_labels_from_tree(struct dt_info *dti, const char *name)
|
||||
{
|
||||
struct node *an;
|
||||
struct property *p;
|
||||
|
||||
an = get_subnode(dti->dt, name);
|
||||
if (!an)
|
||||
return;
|
||||
|
||||
for_each_property(an, p) {
|
||||
struct node *labeled_node;
|
||||
|
||||
labeled_node = get_node_by_path(dti->dt, p->val.val);
|
||||
if (labeled_node)
|
||||
add_label(&labeled_node->labels, p->name);
|
||||
else if (quiet < 1)
|
||||
fprintf(stderr, "Warning: Path %s referenced in property %s/%s missing",
|
||||
p->val.val, name, p->name);
|
||||
}
|
||||
}
|
||||
|
||||
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
|
||||
{
|
||||
if (!any_label_tree(dti, dti->dt))
|
||||
|
|
@ -1130,6 +1151,102 @@ void generate_fixups_tree(struct dt_info *dti, const char *name)
|
|||
name);
|
||||
}
|
||||
|
||||
void fixup_phandles(struct dt_info *dti, const char *name)
|
||||
{
|
||||
struct node *an;
|
||||
struct property *fp;
|
||||
|
||||
an = get_subnode(dti->dt, name);
|
||||
if (!an)
|
||||
return;
|
||||
|
||||
for_each_property(an, fp) {
|
||||
char *fnext = fp->val.val;
|
||||
char *fv;
|
||||
unsigned int fl;
|
||||
|
||||
while ((fl = fp->val.len - (fnext - fp->val.val))) {
|
||||
char *propname, *soffset;
|
||||
struct node *n;
|
||||
struct property *p;
|
||||
long offset;
|
||||
|
||||
fv = fnext;
|
||||
fnext = memchr(fv, 0, fl);
|
||||
|
||||
if (!fnext) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
|
||||
fp->name);
|
||||
break;
|
||||
}
|
||||
fnext += 1;
|
||||
|
||||
propname = memchr(fv, ':', fnext - 1 - fv);
|
||||
if (!propname) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
|
||||
fp->name);
|
||||
continue;
|
||||
}
|
||||
propname++;
|
||||
|
||||
soffset = memchr(propname, ':', fnext - 1 - propname);
|
||||
if (!soffset) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
|
||||
fp->name);
|
||||
continue;
|
||||
}
|
||||
soffset++;
|
||||
|
||||
/*
|
||||
* temporarily modify the property to not have to create
|
||||
* a copy for the node path.
|
||||
*/
|
||||
*(propname - 1) = '\0';
|
||||
|
||||
n = get_node_by_path(dti->dt, fv);
|
||||
if (!n && quiet < 1)
|
||||
fprintf(stderr, "Warning: Label %s references non-existing node %s\n",
|
||||
fp->name, fv);
|
||||
|
||||
*(propname - 1) = ':';
|
||||
|
||||
if (!n)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* temporarily modify the property to not have to create
|
||||
* a copy for the property name.
|
||||
*/
|
||||
*(soffset - 1) = '\0';
|
||||
|
||||
p = get_property(n, propname);
|
||||
|
||||
if (!p && quiet < 1)
|
||||
fprintf(stderr, "Warning: Label %s references non-existing property %s in node %s\n",
|
||||
fp->name, n->fullpath, propname);
|
||||
|
||||
*(soffset - 1) = ':';
|
||||
|
||||
if (!p)
|
||||
continue;
|
||||
|
||||
offset = strtol(soffset, NULL, 0);
|
||||
if (offset < 0 || offset + 4 > p->val.len) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr,
|
||||
"Warning: Label %s contains invalid offset for property %s in node %s\n",
|
||||
fp->name, p->name, n->fullpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
property_add_marker(p, REF_PHANDLE, offset, fp->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generate_local_fixups_tree(struct dt_info *dti, const char *name)
|
||||
{
|
||||
if (!any_local_fixup_tree(dti, dti->dt))
|
||||
|
|
@ -1139,3 +1256,60 @@ void generate_local_fixups_tree(struct dt_info *dti, const char *name)
|
|||
"Warning: Preexisting data in %s malformed, some content could not be added.\n",
|
||||
name);
|
||||
}
|
||||
|
||||
static void local_fixup_phandles_node(struct dt_info *dti, struct node *lf, struct node *n)
|
||||
{
|
||||
struct property *lfp;
|
||||
struct node *lfsubnode;
|
||||
|
||||
for_each_property(lf, lfp) {
|
||||
struct property *p = get_property(n, lfp->name);
|
||||
fdt32_t *offsets = (fdt32_t *)lfp->val.val;
|
||||
size_t i;
|
||||
|
||||
if (!p) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr, "Warning: Property %s in %s referenced in __local_fixups__ missing\n",
|
||||
lfp->name, n->fullpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each property in the __local_fixups__ tree is a concatenation
|
||||
* of offsets, so it must be a multiple of sizeof(fdt32_t).
|
||||
*/
|
||||
if (lfp->val.len % sizeof(fdt32_t)) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr, "Warning: property %s in /__local_fixups__%s malformed\n",
|
||||
lfp->name, n->fullpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < lfp->val.len / sizeof(fdt32_t); i++)
|
||||
add_phandle_marker(dti, p, dtb_ld32(offsets + i));
|
||||
}
|
||||
|
||||
for_each_child(lf, lfsubnode) {
|
||||
struct node *subnode = get_subnode(n, lfsubnode->name);
|
||||
|
||||
if (!subnode) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr, "Warning: node %s/%s referenced in __local_fixups__ missing\n",
|
||||
lfsubnode->name, n->fullpath);
|
||||
continue;
|
||||
}
|
||||
|
||||
local_fixup_phandles_node(dti, lfsubnode, subnode);
|
||||
}
|
||||
}
|
||||
|
||||
void local_fixup_phandles(struct dt_info *dti, const char *name)
|
||||
{
|
||||
struct node *an;
|
||||
|
||||
an = get_subnode(dti->dt, name);
|
||||
if (!an)
|
||||
return;
|
||||
|
||||
local_fixup_phandles_node(dti, an, dti->dt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ add_project_arguments(
|
|||
'-Wshadow',
|
||||
'-Wsuggest-attribute=format',
|
||||
'-Wwrite-strings',
|
||||
'-Wdiscarded-qualifiers',
|
||||
]),
|
||||
language: 'c'
|
||||
)
|
||||
|
|
|
|||
114
treesource.c
114
treesource.c
|
|
@ -173,23 +173,59 @@ static struct marker **add_marker(struct marker **mi,
|
|||
return &nm->next;
|
||||
}
|
||||
|
||||
static void add_string_markers(struct property *prop)
|
||||
void property_add_marker(struct property *prop,
|
||||
enum markertype type, unsigned int offset, char *ref)
|
||||
{
|
||||
int l, len = prop->val.len;
|
||||
const char *p = prop->val.val;
|
||||
add_marker(&prop->val.markers, type, offset, ref);
|
||||
}
|
||||
|
||||
static void add_string_markers(struct property *prop, unsigned int offset, int len)
|
||||
{
|
||||
int l;
|
||||
const char *p = prop->val.val + offset;
|
||||
struct marker **mi = &prop->val.markers;
|
||||
|
||||
for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1)
|
||||
mi = add_marker(mi, TYPE_STRING, l, NULL);
|
||||
mi = add_marker(mi, TYPE_STRING, offset + l, NULL);
|
||||
}
|
||||
|
||||
static enum markertype guess_value_type(struct property *prop)
|
||||
void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset)
|
||||
{
|
||||
int len = prop->val.len;
|
||||
const char *p = prop->val.val;
|
||||
struct marker *m = prop->val.markers;
|
||||
cell_t phandle;
|
||||
struct node *refn;
|
||||
char *ref;
|
||||
|
||||
if (prop->val.len < offset + 4) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr,
|
||||
"Warning: property %s too short to contain a phandle at offset %u\n",
|
||||
prop->name, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
phandle = dtb_ld32(prop->val.val + offset);
|
||||
refn = get_node_by_phandle(dti->dt, phandle);
|
||||
|
||||
if (!refn) {
|
||||
if (quiet < 1)
|
||||
fprintf(stderr,
|
||||
"Warning: node referenced by phandle 0x%x in property %s not found\n",
|
||||
phandle, prop->name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (refn->labels)
|
||||
ref = refn->labels->label;
|
||||
else
|
||||
ref = refn->fullpath;
|
||||
|
||||
add_marker(&prop->val.markers, REF_PHANDLE, offset, ref);
|
||||
}
|
||||
|
||||
static enum markertype guess_value_type(struct property *prop, unsigned int offset, int len)
|
||||
{
|
||||
const char *p = prop->val.val + offset;
|
||||
int nnotstring = 0, nnul = 0;
|
||||
int nnotstringlbl = 0, nnotcelllbl = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
|
@ -199,30 +235,49 @@ static enum markertype guess_value_type(struct property *prop)
|
|||
nnul++;
|
||||
}
|
||||
|
||||
for_each_marker_of_type(m, LABEL) {
|
||||
if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
|
||||
nnotstringlbl++;
|
||||
if ((m->offset % sizeof(cell_t)) != 0)
|
||||
nnotcelllbl++;
|
||||
}
|
||||
|
||||
if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
|
||||
&& (nnotstringlbl == 0)) {
|
||||
if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= len - nnul)) {
|
||||
if (nnul > 1)
|
||||
add_string_markers(prop);
|
||||
add_string_markers(prop, offset, len);
|
||||
return TYPE_STRING;
|
||||
} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
|
||||
} else if ((len % sizeof(cell_t)) == 0) {
|
||||
return TYPE_UINT32;
|
||||
}
|
||||
|
||||
return TYPE_UINT8;
|
||||
}
|
||||
|
||||
static void guess_type_markers(struct property *prop)
|
||||
{
|
||||
struct marker **m = &prop->val.markers;
|
||||
unsigned int offset = 0;
|
||||
|
||||
for (m = &prop->val.markers; *m; m = &((*m)->next)) {
|
||||
if (is_type_marker((*m)->type))
|
||||
/* assume the whole property is already marked */
|
||||
return;
|
||||
|
||||
if ((*m)->offset > offset) {
|
||||
m = add_marker(m, guess_value_type(prop, offset, (*m)->offset - offset),
|
||||
offset, NULL);
|
||||
|
||||
offset = (*m)->offset;
|
||||
}
|
||||
|
||||
if ((*m)->type == REF_PHANDLE) {
|
||||
m = add_marker(m, TYPE_UINT32, offset, NULL);
|
||||
offset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset < prop->val.len)
|
||||
add_marker(m, guess_value_type(prop, offset, prop->val.len - offset),
|
||||
offset, NULL);
|
||||
}
|
||||
|
||||
static void write_propval(FILE *f, struct property *prop)
|
||||
{
|
||||
size_t len = prop->val.len;
|
||||
struct marker *m = prop->val.markers;
|
||||
struct marker dummy_marker;
|
||||
struct marker *m;
|
||||
enum markertype emit_type = TYPE_NONE;
|
||||
char *srcstr;
|
||||
|
||||
|
|
@ -241,14 +296,8 @@ static void write_propval(FILE *f, struct property *prop)
|
|||
|
||||
fprintf(f, " =");
|
||||
|
||||
if (!next_type_marker(m)) {
|
||||
/* data type information missing, need to guess */
|
||||
dummy_marker.type = guess_value_type(prop);
|
||||
dummy_marker.next = prop->val.markers;
|
||||
dummy_marker.offset = 0;
|
||||
dummy_marker.ref = NULL;
|
||||
m = &dummy_marker;
|
||||
}
|
||||
guess_type_markers(prop);
|
||||
m = prop->val.markers;
|
||||
|
||||
for_each_marker(m) {
|
||||
size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
|
||||
|
|
@ -369,7 +418,10 @@ void dt_to_source(FILE *f, struct dt_info *dti)
|
|||
{
|
||||
struct reserve_info *re;
|
||||
|
||||
fprintf(f, "/dts-v1/;\n\n");
|
||||
fprintf(f, "/dts-v1/;\n");
|
||||
if (dti->dtsflags & DTSF_PLUGIN)
|
||||
fprintf(f, "/plugin/;\n");
|
||||
fprintf(f, "\n");
|
||||
|
||||
for (re = dti->reservelist; re; re = re->next) {
|
||||
struct label *l;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue