From: Frank Rowand <frank.rowand@sonymobile.com>

Fix dtdiff for .dts files in the Linux kernel source tree

The dtdiff tool maintained at
git://git.kernel.org/pub/scm/utils/dtc/dtc.git
does not properly handle many of the .dts files in the Linux kernel source
tree because

   - file path of .dts files is not supplied to dtc
   - /include/ file path is not supplied to dtc
   - .dts files are not pre-processed by cpp

This patch is a quick and dirty solution for those issues.  The best place for
this patch might be the linux kernel source tree.

Get DTC_FLAGS from the architecture specific Makefile.

Add patch kernel/dts/ to the include paths.

Add single parameter option that does a decompile of that file.

Add a parameter to disable sort.

Add a parameter to force entire input files to be printed, not just a
limited context around the differences.

Add usage message.

Applies cleanly on top of:
   commit 37c0b6a0916c31a5eae0a9ddfcc5d0b8fb4569c6
   Date:   Wed Nov 10 09:51:09 2010 +1100

Signed-off-by: Frank Rowand <frank.rowand@sonymobile.com>
---
 dtdiff |  204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 185 insertions(+), 19 deletions(-)

Index: b/dtdiff
===================================================================
--- a/dtdiff
+++ b/dtdiff
@@ -1,38 +1,204 @@
 #! /bin/bash
 
+# This script expects .dts file to be in the Linux kernel source tree.  The
+# .dts is pre-processed before being compiled by dtc.  This allows for
+# includes of files in their normal location in the linux kernel source tree.
+
 # This script uses the bash <(...) extension.
-# If you want to change this to work with a generic /bin/sh, make sure
+# If you want to change this script to work with a generic /bin/sh, make sure
 # you fix that.
 
+# Inspired by dtdiff by David Gibson at
+#   git://git.kernel.org/pub/scm/utils/dtc/dtc.git.
+# as of commit 37c0b6a0916c31a5eae0a9ddfcc5d0b8fb4569c6
+#       Date:   Wed Nov 10 09:51:09 2010 +1100
+#
+# It is not clear what the license on that file is, but possibly GPL.  I would
+# like to license this file as GPL V2, but the final decision awaits confirming
+# that is compatible with the license of the David Gibson dtdiff, or
+# determining that the amount of code copied from there is too minimal to
+# require permission to copy.
 
-DTC=dtc
 
 source_and_sort () {
+
+    # XXX Tried putting the pipe at the end of the define of CPP in the
+    # XXX    *.dts case, but cpp choked.  Workaround, move the pipe to
+    # XXX    the line where $CPP is used
+    # XXX    This can maybe instead be fixed by doing eval $CPP
+
+    CPP="cat /dev/null"
     DT="$1"
     if [ -d "$DT" ]; then
-	IFORMAT=fs
+        IFORMAT=fs
     elif [ -f "$DT" ]; then
-	case "$DT" in
-	    *.dts)
-		IFORMAT=dts
-		;;
-	    *.dtb)
-		IFORMAT=dtb
-		;;
-	esac
+        case "$DT" in
+            *.dts)
+                IFORMAT=dts
+                CPP="cpp ${cpp_flags} -x assembler-with-cpp $DT"
+                # empty DT __after__ using it in previous line
+                DT=""
+                ;;
+            *.dtb)
+                IFORMAT=dtb
+                ;;
+        esac
     fi
 
-    if [ -z "$IFORMAT" ]; then
-	echo "Unrecognized format for $DT" >&2
-	exit 2
+    if [ -z "${IFORMAT}" ]; then
+        echo "Unrecognized format for ${DT}"                                 >&2
+        exit 2
     fi
 
-    $DTC -I $IFORMAT -O dts -qq -f -s -o - "$DT"
+    ${CPP} | ${DTC} -I ${IFORMAT} -O dts -qq -f ${dtc_sort} -o - ${DT}
 }
 
-if [ $# != 2 ]; then
-    echo "Usage: dtdiff <device tree> <device tree>" >&2
-    exit 1
+cmd_decomp=0
+cmd_diff=0
+dt_file_1=""
+dt_file_2=""
+diff_u_9999=0
+dtc_sort="-s"
+srctree=""
+
+
+while [[ ($# -gt 0) ]] ; do
+
+    case $1 in
+
+    -f )
+        shift
+        diff_u_9999=1
+        ;;
+
+    -h | -help | --help )
+        shift
+        help=1
+        ;;
+
+    -s )
+        shift
+        srctree="$1"
+        ;;
+
+    -u )
+        shift
+        dtc_sort=""
+        ;;
+
+    *)
+        if [[ "${dt_file_1}"  == "" ]] ; then
+            dt_file_1="$1"
+        elif [[ "${dt_file_2}" == "" ]] ; then
+            dt_file_2="$1"
+        else
+            echo "Unexpected parameter: $1"                                  >&2
+        fi
+        shift
+        ;;
+
+    esac
+
+done
+
+
+if [ "${dt_file_2}" == "" ]; then
+    cmd_decomp=1
+else
+    cmd_diff=1
+fi
+
+
+if [[ ${help} -eq 1 ]] ; then
+
+echo "Usage:"                                                                >&2
+echo ""                                                                      >&2
+echo "    `basename $0` DEVICE_TREE"                                         >&2
+echo "        decompiles DEVICE_TREE"                                        >&2
+echo ""                                                                      >&2
+echo "    `basename $0` DEVICE_TREE_1 DEVICE_TREE_2"                         >&2
+echo "        diffs two device trees"                                        >&2
+echo ""                                                                      >&2
+echo ""                                                                      >&2
+echo "       -f           print full dts in diff (--unified=9999)"           >&2
+echo "       -h           synonym for --help"                                >&2
+echo "       -help        synonym for --help"                                >&2
+echo "      --help        print this message and exit"                       >&2
+echo "       -s SRCTREE   linux kernel source tree is at path SRCTREE"       >&2
+echo "       -u           unsorted, do not pass the sort option to dtc"      >&2
+echo ""                                                                      >&2
+echo ""                                                                      >&2
+echo "  If <device tree> ends with .dbs, it is treated as binary blob"       >&2
+echo "  If <device tree> ends with .dts, it is treated as source"            >&2
+echo "  If <device tree> is a directory, it is treated as DT subtree"        >&2
+echo "     such as /proc/device-tree"                                        >&2
+echo ""                                                                      >&2
+echo "  If this script is not run from the root of the linux source"         >&2
+echo "  tree, then the path of the linux source tree must be provided"       >&2
+echo "  by the '-s' flag."                                                   >&2
+echo ""                                                                      >&2
+echo "  The shell variable 'ARCH' must contain the architecture"             >&2
+echo "  containing the .dts file."                                           >&2
+echo ""                                                                      >&2
+
+exit 1
+fi
+
+
+if [[ "${srctree}" == "" ]] ; then
+    srctree="."
 fi
 
-diff -u <(source_and_sort "$1") <(source_and_sort "$2")
+if [[ ! -d ${srctree}/arch/${ARCH} ]] ; then
+    echo "WARNING: directory '${ARCH}' does not exist"                       >&2
+fi
+
+
+cpp_flags="\
+    -nostdinc                                              \
+    -I${srctree}/arch/${ARCH}/boot/dts                     \
+    -I${srctree}/arch/${ARCH}/boot/dts/include             \
+    -I${srctree}/arch/${ARCH}/boot/dts/include/dt-bindings \
+    -I${srctree}/drivers/of/testcase-data                  \
+    -I${srctree}/kernel/dts                                \
+    -undef -D__DTS__"
+
+DTC_FLAGS=""
+_dts_makefile=""
+
+if [[ -f ${srctree}/arch/${ARCH}/boot/dts/Makefile ]] ; then
+    _dts_makefile="${srctree}/arch/${ARCH}/boot/dts/Makefile"
+elif [[ -f ${srctree}/arch/${ARCH}/boot/Makefile ]] ; then
+    _dts_makefile="${srctree}/arch/${ARCH}/boot/Makefile"
+fi
+
+if [[ "${_dts_makefile}" != "" ]] ; then
+    arch_dtc_flags=`grep DTC_FLAGS ${_dts_makefile} \
+        | grep -v "^#"                              \
+        | sed -e 's|.*=||' `
+else
+    arch_dtc_flags=""
+fi
+
+dtc_flags="\
+    -i ${srctree}/arch/${ARCH}/boot/dts/ \
+    -i ${srctree}/kernel/dts             \
+    ${arch_dtc_flags}"
+
+DTC="dtc ${dtc_flags}"
+
+if [[ ${diff_u_9999} -eq 1 ]] ; then
+    diff_flags="--unified=9999"
+else
+    diff_flags="-u"
+fi
+
+if [[ ${cmd_diff} == 1 ]] ; then
+    diff ${diff_flags} \
+        <(source_and_sort "${dt_file_1}") \
+        <(source_and_sort "${dt_file_2}")
+elif [[ ${cmd_decomp} == 1 ]] ; then
+    source_and_sort "${dt_file_1}"
+fi
+
+
