Skip to content

Commit

Permalink
dtc: Add code to make diffing trees easier
Browse files Browse the repository at this point in the history
This patch adds a "dtdiff" script to do a useful form diff of two
device trees.  This automatically converts the tree to dts form (if
it's not already) and uses a new "-s" option in dtc to "sort" the
tree.  That is, it sorts the reserve entries, it sorts the properties
within each node by name, and it sorts nodes by name within their
parent.

This gives a pretty sensible diff between the trees, which will ignore
semantically null internal rearrangements (directly diffing the dts
files can give a lot of noise due to the order changes).

Signed-off-by: David Gibson <[email protected]>
  • Loading branch information
dgibson authored and Jon Loeliger committed Nov 13, 2010
1 parent 73ae43e commit 37c0b6a
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 4 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ BIN += convert-dtsv0
BIN += dtc
BIN += ftdump

SCRIPTS = dtdiff

all: $(BIN) libfdt

Expand Down Expand Up @@ -155,10 +156,10 @@ endif
# intermediate target and building them again "for real"
.SECONDARY: $(DTC_GEN_SRCS) $(CONVERT_GEN_SRCS)

install: all
install: all $(SCRIPTS)
@$(VECHO) INSTALL
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) $(BIN) $(DESTDIR)$(BINDIR)
$(INSTALL) $(BIN) $(SCRIPTS) $(DESTDIR)$(BINDIR)
$(INSTALL) -d $(DESTDIR)$(LIBDIR)
$(INSTALL) $(LIBFDT_lib) $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 644 $(LIBFDT_archive) $(DESTDIR)$(LIBDIR)
Expand Down
12 changes: 10 additions & 2 deletions dtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ static void __attribute__ ((noreturn)) usage(void)
fprintf(stderr, "\t\tSet the physical boot cpu\n");
fprintf(stderr, "\t-f\n");
fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
fprintf(stderr, "\t-s\n");
fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
fprintf(stderr, "\t-v\n");
fprintf(stderr, "\t\tPrint DTC version and exit\n");
fprintf(stderr, "\t-H <phandle format>\n");
Expand All @@ -97,7 +99,7 @@ int main(int argc, char *argv[])
const char *inform = "dts";
const char *outform = "dts";
const char *outname = "-";
int force = 0, check = 0;
int force = 0, check = 0, sort = 0;
const char *arg;
int opt;
FILE *outf = NULL;
Expand All @@ -109,7 +111,7 @@ int main(int argc, char *argv[])
minsize = 0;
padsize = 0;

while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:")) != EOF) {
while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:s")) != EOF) {
switch (opt) {
case 'I':
inform = optarg;
Expand Down Expand Up @@ -159,6 +161,10 @@ int main(int argc, char *argv[])
optarg);
break;

case 's':
sort = 1;
break;

case 'h':
default:
usage();
Expand Down Expand Up @@ -197,6 +203,8 @@ int main(int argc, char *argv[])
fill_fullpaths(bi->dt, "");
process_checks(force, bi);

if (sort)
sort_tree(bi);

if (streq(outname, "-")) {
outf = stdout;
Expand Down
1 change: 1 addition & 0 deletions dtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ struct boot_info {

struct boot_info *build_boot_info(struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys);
void sort_tree(struct boot_info *bi);

/* Checks */

Expand Down
38 changes: 38 additions & 0 deletions dtdiff
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#! /bin/bash

# This script uses the bash <(...) extension.
# If you want to change this to work with a generic /bin/sh, make sure
# you fix that.


DTC=dtc

source_and_sort () {
DT="$1"
if [ -d "$DT" ]; then
IFORMAT=fs
elif [ -f "$DT" ]; then
case "$DT" in
*.dts)
IFORMAT=dts
;;
*.dtb)
IFORMAT=dtb
;;
esac
fi

if [ -z "$IFORMAT" ]; then
echo "Unrecognized format for $DT" >&2
exit 2
fi

$DTC -I $IFORMAT -O dts -qq -f -s -o - "$DT"
}

if [ $# != 2 ]; then
echo "Usage: dtdiff <device tree> <device tree>" >&2
exit 1
fi

diff -u <(source_and_sort "$1") <(source_and_sort "$2")
137 changes: 137 additions & 0 deletions livetree.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,3 +470,140 @@ uint32_t guess_boot_cpuid(struct node *tree)

return propval_cell(reg);
}

static int cmp_reserve_info(const void *ax, const void *bx)
{
const struct reserve_info *a, *b;

a = *((const struct reserve_info * const *)ax);
b = *((const struct reserve_info * const *)bx);

if (a->re.address < b->re.address)
return -1;
else if (a->re.address > b->re.address)
return 1;
else if (a->re.size < b->re.size)
return -1;
else if (a->re.size > b->re.size)
return 1;
else
return 0;
}

static void sort_reserve_entries(struct boot_info *bi)
{
struct reserve_info *ri, **tbl;
int n = 0, i = 0;

for (ri = bi->reservelist;
ri;
ri = ri->next)
n++;

if (n == 0)
return;

tbl = xmalloc(n * sizeof(*tbl));

for (ri = bi->reservelist;
ri;
ri = ri->next)
tbl[i++] = ri;

qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);

bi->reservelist = tbl[0];
for (i = 0; i < (n-1); i++)
tbl[i]->next = tbl[i+1];
tbl[n-1]->next = NULL;

free(tbl);
}

static int cmp_prop(const void *ax, const void *bx)
{
const struct property *a, *b;

a = *((const struct property * const *)ax);
b = *((const struct property * const *)bx);

return strcmp(a->name, b->name);
}

static void sort_properties(struct node *node)
{
int n = 0, i = 0;
struct property *prop, **tbl;

for_each_property(node, prop)
n++;

if (n == 0)
return;

tbl = xmalloc(n * sizeof(*tbl));

for_each_property(node, prop)
tbl[i++] = prop;

qsort(tbl, n, sizeof(*tbl), cmp_prop);

node->proplist = tbl[0];
for (i = 0; i < (n-1); i++)
tbl[i]->next = tbl[i+1];
tbl[n-1]->next = NULL;

free(tbl);
}

static int cmp_subnode(const void *ax, const void *bx)
{
const struct node *a, *b;

a = *((const struct node * const *)ax);
b = *((const struct node * const *)bx);

return strcmp(a->name, b->name);
}

static void sort_subnodes(struct node *node)
{
int n = 0, i = 0;
struct node *subnode, **tbl;

for_each_child(node, subnode)
n++;

if (n == 0)
return;

tbl = xmalloc(n * sizeof(*tbl));

for_each_child(node, subnode)
tbl[i++] = subnode;

qsort(tbl, n, sizeof(*tbl), cmp_subnode);

node->children = tbl[0];
for (i = 0; i < (n-1); i++)
tbl[i]->next_sibling = tbl[i+1];
tbl[n-1]->next_sibling = NULL;

free(tbl);
}

static void sort_node(struct node *node)
{
struct node *c;

sort_properties(node);
sort_subnodes(node);
for_each_child(node, c)
sort_node(c);
}

void sort_tree(struct boot_info *bi)
{
sort_reserve_entries(bi);
sort_node(bi->dt);
}
7 changes: 7 additions & 0 deletions tests/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,13 @@ cmp_tests () {
for tree in $wrongtrees; do
run_test dtbs_equal_unordered -n $basetree $tree
done

# now dtc --sort
run_dtc_test -I dtb -O dtb -s -o $basetree.sorted.test.dtb $basetree
run_test dtbs_equal_unordered $basetree $basetree.sorted.test.dtb
run_dtc_test -I dtb -O dtb -s -o $basetree.reversed.sorted.test.dtb $basetree.reversed.test.dtb
run_test dtbs_equal_unordered $basetree.reversed.test.dtb $basetree.reversed.sorted.test.dtb
run_test dtbs_equal_ordered $basetree.sorted.test.dtb $basetree.reversed.sorted.test.dtb
}

dtbs_equal_tests () {
Expand Down

0 comments on commit 37c0b6a

Please sign in to comment.