1*10eadc25SFrank Rowand#! /bin/bash 2*10eadc25SFrank Rowand 3*10eadc25SFrank Rowand# Copyright (C) 2015 Frank Rowand 4*10eadc25SFrank Rowand# 5*10eadc25SFrank Rowand# This program is free software; you can redistribute it and/or modify 6*10eadc25SFrank Rowand# it under the terms of the GNU General Public License as published by 7*10eadc25SFrank Rowand# the Free Software Foundation; version 2 of the License. 8*10eadc25SFrank Rowand 9*10eadc25SFrank Rowand 10*10eadc25SFrank Rowandusage() { 11*10eadc25SFrank Rowand 12*10eadc25SFrank Rowand # use spaces instead of tabs in the usage message 13*10eadc25SFrank Rowand cat >&2 <<eod 14*10eadc25SFrank Rowand 15*10eadc25SFrank RowandUsage: 16*10eadc25SFrank Rowand 17*10eadc25SFrank Rowand `basename $0` DTx 18*10eadc25SFrank Rowand decompile DTx 19*10eadc25SFrank Rowand 20*10eadc25SFrank Rowand `basename $0` DTx_1 DTx_2 21*10eadc25SFrank Rowand diff DTx_1 and DTx_2 22*10eadc25SFrank Rowand 23*10eadc25SFrank Rowand 24*10eadc25SFrank Rowand -f print full dts in diff (--unified=99999) 25*10eadc25SFrank Rowand -h synonym for --help 26*10eadc25SFrank Rowand -help synonym for --help 27*10eadc25SFrank Rowand --help print this message and exit 28*10eadc25SFrank Rowand -s SRCTREE linux kernel source tree is at path SRCTREE 29*10eadc25SFrank Rowand (default is current directory) 30*10eadc25SFrank Rowand -S linux kernel source tree is at root of current git repo 31*10eadc25SFrank Rowand -u unsorted, do not sort DTx 32*10eadc25SFrank Rowand 33*10eadc25SFrank Rowand 34*10eadc25SFrank RowandEach DTx is processed by the dtc compiler to produce a sorted dts source 35*10eadc25SFrank Rowandfile. If DTx is a dts source file then it is pre-processed in the same 36*10eadc25SFrank Rowandmanner as done for the compile of the dts source file in the Linux kernel 37*10eadc25SFrank Rowandbuild system ('#include' and '/include/' directives are processed). 38*10eadc25SFrank Rowand 39*10eadc25SFrank RowandIf two DTx are provided, the resulting dts source files are diffed. 40*10eadc25SFrank Rowand 41*10eadc25SFrank RowandIf DTx is a directory, it is treated as a DT subtree, such as 42*10eadc25SFrank Rowand /proc/device-tree. 43*10eadc25SFrank Rowand 44*10eadc25SFrank RowandIf DTx contains the binary blob magic value in the first four bytes, 45*10eadc25SFrank Rowand it is treated as a binary blob (aka .dtb or FDT). 46*10eadc25SFrank Rowand 47*10eadc25SFrank RowandOtherwise DTx is treated as a dts source file (aka .dts). 48*10eadc25SFrank Rowand 49*10eadc25SFrank Rowand If this script is not run from the root of the linux source tree, 50*10eadc25SFrank Rowand and DTx utilizes '#include' or '/include/' then the path of the 51*10eadc25SFrank Rowand linux source tree can be provided by '-s SRCTREE' or '-S' so that 52*10eadc25SFrank Rowand include paths will be set properly. 53*10eadc25SFrank Rowand 54*10eadc25SFrank Rowand The shell variable \${ARCH} must provide the architecture containing 55*10eadc25SFrank Rowand the dts source file for include paths to be set properly for '#include' 56*10eadc25SFrank Rowand or '/include/' to be processed. 57*10eadc25SFrank Rowand 58*10eadc25SFrank Rowand If DTx_1 and DTx_2 are in different architectures, then this script 59*10eadc25SFrank Rowand may not work since \${ARCH} is part of the include path. Two possible 60*10eadc25SFrank Rowand workarounds: 61*10eadc25SFrank Rowand 62*10eadc25SFrank Rowand `basename $0` \\ 63*10eadc25SFrank Rowand <(ARCH=arch_of_dtx_1 `basename $0` DTx_1) \\ 64*10eadc25SFrank Rowand <(ARCH=arch_of_dtx_2 `basename $0` DTx_2) 65*10eadc25SFrank Rowand 66*10eadc25SFrank Rowand `basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts 67*10eadc25SFrank Rowand `basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts 68*10eadc25SFrank Rowand `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts 69*10eadc25SFrank Rowand rm tmp_dtx_1.dts tmp_dtx_2.dts 70*10eadc25SFrank Rowand 71*10eadc25SFrank Rowand If DTx_1 and DTx_2 are in different directories, then this script will 72*10eadc25SFrank Rowand add the path of DTx_1 and DTx_2 to the include paths. If DTx_2 includes 73*10eadc25SFrank Rowand a local file that exists in both the path of DTx_1 and DTx_2 then the 74*10eadc25SFrank Rowand file in the path of DTx_1 will incorrectly be included. Possible 75*10eadc25SFrank Rowand workaround: 76*10eadc25SFrank Rowand 77*10eadc25SFrank Rowand `basename $0` DTx_1 >tmp_dtx_1.dts 78*10eadc25SFrank Rowand `basename $0` DTx_2 >tmp_dtx_2.dts 79*10eadc25SFrank Rowand `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts 80*10eadc25SFrank Rowand rm tmp_dtx_1.dts tmp_dtx_2.dts 81*10eadc25SFrank Rowand 82*10eadc25SFrank Rowandeod 83*10eadc25SFrank Rowand} 84*10eadc25SFrank Rowand 85*10eadc25SFrank Rowand 86*10eadc25SFrank Rowandcompile_to_dts() { 87*10eadc25SFrank Rowand 88*10eadc25SFrank Rowand dtx="$1" 89*10eadc25SFrank Rowand 90*10eadc25SFrank Rowand if [ -d "${dtx}" ] ; then 91*10eadc25SFrank Rowand 92*10eadc25SFrank Rowand # ----- input is file tree 93*10eadc25SFrank Rowand 94*10eadc25SFrank Rowand if ( ! ${DTC} -I fs ${dtx} ) ; then 95*10eadc25SFrank Rowand exit 3 96*10eadc25SFrank Rowand fi 97*10eadc25SFrank Rowand 98*10eadc25SFrank Rowand elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then 99*10eadc25SFrank Rowand 100*10eadc25SFrank Rowand magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}` 101*10eadc25SFrank Rowand if [ "${magic}" = "d00dfeed" ] ; then 102*10eadc25SFrank Rowand 103*10eadc25SFrank Rowand # ----- input is FDT (binary blob) 104*10eadc25SFrank Rowand 105*10eadc25SFrank Rowand if ( ! ${DTC} -I dtb ${dtx} ) ; then 106*10eadc25SFrank Rowand exit 3 107*10eadc25SFrank Rowand fi 108*10eadc25SFrank Rowand 109*10eadc25SFrank Rowand return 110*10eadc25SFrank Rowand 111*10eadc25SFrank Rowand fi 112*10eadc25SFrank Rowand 113*10eadc25SFrank Rowand # ----- input is DTS (source) 114*10eadc25SFrank Rowand 115*10eadc25SFrank Rowand if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \ 116*10eadc25SFrank Rowand | ${DTC} -I dts ) ; then 117*10eadc25SFrank Rowand return 118*10eadc25SFrank Rowand fi 119*10eadc25SFrank Rowand 120*10eadc25SFrank Rowand echo "" >&2 121*10eadc25SFrank Rowand echo "Possible hints to resolve the above error:" >&2 122*10eadc25SFrank Rowand echo " (hints might not fix the problem)" >&2 123*10eadc25SFrank Rowand 124*10eadc25SFrank Rowand hint_given=0 125*10eadc25SFrank Rowand 126*10eadc25SFrank Rowand if [ "${ARCH}" = "" ] ; then 127*10eadc25SFrank Rowand hint_given=1 128*10eadc25SFrank Rowand echo "" >&2 129*10eadc25SFrank Rowand echo " shell variable \$ARCH not set" >&2 130*10eadc25SFrank Rowand fi 131*10eadc25SFrank Rowand 132*10eadc25SFrank Rowand dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'` 133*10eadc25SFrank Rowand 134*10eadc25SFrank Rowand if [ "${dtx_arch}" != "" -a "${dtx_arch}" != "${ARCH}" ] ; then 135*10eadc25SFrank Rowand hint_given=1 136*10eadc25SFrank Rowand echo "" >&2 137*10eadc25SFrank Rowand echo " architecture ${dtx_arch} is in file path," >&2 138*10eadc25SFrank Rowand echo " but does not match shell variable \$ARCH" >&2 139*10eadc25SFrank Rowand echo " (${ARCH}) does not match shell variable" >&2 140*10eadc25SFrank Rowand echo " \$ARCH (${ARCH})" >&2 141*10eadc25SFrank Rowand fi 142*10eadc25SFrank Rowand 143*10eadc25SFrank Rowand if [ ! -d ${srctree}/arch/${ARCH} ] ; then 144*10eadc25SFrank Rowand hint_given=1 145*10eadc25SFrank Rowand echo "" >&2 146*10eadc25SFrank Rowand echo " ${srctree}/arch/${ARCH}/ does not exist" >&2 147*10eadc25SFrank Rowand echo " Is \$ARCH='${ARCH}' correct?" >&2 148*10eadc25SFrank Rowand echo " Possible fix: use '-s' option" >&2 149*10eadc25SFrank Rowand 150*10eadc25SFrank Rowand git_root=`git rev-parse --show-toplevel 2>/dev/null` 151*10eadc25SFrank Rowand if [ -d ${git_root}/arch/ ] ; then 152*10eadc25SFrank Rowand echo " Possible fix: use '-S' option" >&2 153*10eadc25SFrank Rowand fi 154*10eadc25SFrank Rowand fi 155*10eadc25SFrank Rowand 156*10eadc25SFrank Rowand if [ $hint_given = 0 ] ; then 157*10eadc25SFrank Rowand echo "" >&2 158*10eadc25SFrank Rowand echo " No hints available." >&2 159*10eadc25SFrank Rowand fi 160*10eadc25SFrank Rowand 161*10eadc25SFrank Rowand echo "" >&2 162*10eadc25SFrank Rowand 163*10eadc25SFrank Rowand exit 3 164*10eadc25SFrank Rowand 165*10eadc25SFrank Rowand else 166*10eadc25SFrank Rowand echo "" >&2 167*10eadc25SFrank Rowand echo "ERROR: ${dtx} does not exist or is not readable" >&2 168*10eadc25SFrank Rowand echo "" >&2 169*10eadc25SFrank Rowand exit 2 170*10eadc25SFrank Rowand fi 171*10eadc25SFrank Rowand 172*10eadc25SFrank Rowand} 173*10eadc25SFrank Rowand 174*10eadc25SFrank Rowand 175*10eadc25SFrank Rowand# ----- start of script 176*10eadc25SFrank Rowand 177*10eadc25SFrank Rowandcmd_diff=0 178*10eadc25SFrank Rowanddiff_flags="-u" 179*10eadc25SFrank Rowanddtx_file_1="" 180*10eadc25SFrank Rowanddtx_file_2="" 181*10eadc25SFrank Rowanddtc_sort="-s" 182*10eadc25SFrank Rowandhelp=0 183*10eadc25SFrank Rowandsrctree="" 184*10eadc25SFrank Rowand 185*10eadc25SFrank Rowand 186*10eadc25SFrank Rowandwhile [ $# -gt 0 ] ; do 187*10eadc25SFrank Rowand 188*10eadc25SFrank Rowand case $1 in 189*10eadc25SFrank Rowand 190*10eadc25SFrank Rowand -f ) 191*10eadc25SFrank Rowand diff_flags="--unified=999999" 192*10eadc25SFrank Rowand shift 193*10eadc25SFrank Rowand ;; 194*10eadc25SFrank Rowand 195*10eadc25SFrank Rowand -h | -help | --help ) 196*10eadc25SFrank Rowand help=1 197*10eadc25SFrank Rowand shift 198*10eadc25SFrank Rowand ;; 199*10eadc25SFrank Rowand 200*10eadc25SFrank Rowand -s ) 201*10eadc25SFrank Rowand srctree="$2" 202*10eadc25SFrank Rowand shift 2 203*10eadc25SFrank Rowand ;; 204*10eadc25SFrank Rowand 205*10eadc25SFrank Rowand -S ) 206*10eadc25SFrank Rowand git_root=`git rev-parse --show-toplevel 2>/dev/null` 207*10eadc25SFrank Rowand srctree="${git_root}" 208*10eadc25SFrank Rowand shift 209*10eadc25SFrank Rowand ;; 210*10eadc25SFrank Rowand 211*10eadc25SFrank Rowand -u ) 212*10eadc25SFrank Rowand dtc_sort="" 213*10eadc25SFrank Rowand shift 214*10eadc25SFrank Rowand ;; 215*10eadc25SFrank Rowand 216*10eadc25SFrank Rowand *) 217*10eadc25SFrank Rowand if [ "${dtx_file_1}" = "" ] ; then 218*10eadc25SFrank Rowand dtx_file_1="$1" 219*10eadc25SFrank Rowand elif [ "${dtx_file_2}" = "" ] ; then 220*10eadc25SFrank Rowand dtx_file_2="$1" 221*10eadc25SFrank Rowand else 222*10eadc25SFrank Rowand echo "" >&2 223*10eadc25SFrank Rowand echo "ERROR: Unexpected parameter: $1" >&2 224*10eadc25SFrank Rowand echo "" >&2 225*10eadc25SFrank Rowand exit 2 226*10eadc25SFrank Rowand fi 227*10eadc25SFrank Rowand shift 228*10eadc25SFrank Rowand ;; 229*10eadc25SFrank Rowand 230*10eadc25SFrank Rowand esac 231*10eadc25SFrank Rowand 232*10eadc25SFrank Rowanddone 233*10eadc25SFrank Rowand 234*10eadc25SFrank Rowandif [ "${srctree}" = "" ] ; then 235*10eadc25SFrank Rowand srctree="." 236*10eadc25SFrank Rowandfi 237*10eadc25SFrank Rowand 238*10eadc25SFrank Rowandif [ "${dtx_file_2}" != "" ]; then 239*10eadc25SFrank Rowand cmd_diff=1 240*10eadc25SFrank Rowandfi 241*10eadc25SFrank Rowand 242*10eadc25SFrank Rowandif (( ${help} )) ; then 243*10eadc25SFrank Rowand usage 244*10eadc25SFrank Rowand exit 1 245*10eadc25SFrank Rowandfi 246*10eadc25SFrank Rowand 247*10eadc25SFrank Rowand# this must follow check for ${help} 248*10eadc25SFrank Rowandif [ "${dtx_file_1}" = "" ]; then 249*10eadc25SFrank Rowand echo "" >&2 250*10eadc25SFrank Rowand echo "ERROR: parameter DTx required" >&2 251*10eadc25SFrank Rowand echo "" >&2 252*10eadc25SFrank Rowand exit 2 253*10eadc25SFrank Rowandfi 254*10eadc25SFrank Rowand 255*10eadc25SFrank Rowand 256*10eadc25SFrank Rowand# ----- prefer dtc from linux kernel, allow fallback to dtc in $PATH 257*10eadc25SFrank Rowand 258*10eadc25SFrank Rowandif [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then 259*10eadc25SFrank Rowand __KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}" 260*10eadc25SFrank Rowandelif [ "${KBUILD_OUTPUT}" = "" ] ; then 261*10eadc25SFrank Rowand __KBUILD_OUTPUT="." 262*10eadc25SFrank Rowandelse 263*10eadc25SFrank Rowand __KBUILD_OUTPUT="${KBUILD_OUTPUT}" 264*10eadc25SFrank Rowandfi 265*10eadc25SFrank Rowand 266*10eadc25SFrank RowandDTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc" 267*10eadc25SFrank Rowand 268*10eadc25SFrank Rowandif [ ! -x ${DTC} ] ; then 269*10eadc25SFrank Rowand __DTC="dtc" 270*10eadc25SFrank Rowand if ( ! which ${__DTC} >/dev/null ) ; then 271*10eadc25SFrank Rowand 272*10eadc25SFrank Rowand # use spaces instead of tabs in the error message 273*10eadc25SFrank Rowand cat >&2 <<eod 274*10eadc25SFrank Rowand 275*10eadc25SFrank RowandERROR: unable to find a 'dtc' program 276*10eadc25SFrank Rowand 277*10eadc25SFrank Rowand Preferred 'dtc' (built from Linux kernel source tree) was not found or 278*10eadc25SFrank Rowand is not executable. 279*10eadc25SFrank Rowand 280*10eadc25SFrank Rowand 'dtc' is: ${DTC} 281*10eadc25SFrank Rowand 282*10eadc25SFrank Rowand If it does not exist, create it from the root of the Linux source tree: 283*10eadc25SFrank Rowand 284*10eadc25SFrank Rowand 'make scripts'. 285*10eadc25SFrank Rowand 286*10eadc25SFrank Rowand If not at the root of the Linux kernel source tree -s SRCTREE or -S 287*10eadc25SFrank Rowand may need to be specified to find 'dtc'. 288*10eadc25SFrank Rowand 289*10eadc25SFrank Rowand If 'O=\${dir}' is specified in your Linux builds, this script requires 290*10eadc25SFrank Rowand 'export KBUILD_OUTPUT=\${dir}' or add \${dir}/scripts/dtc to \$PATH 291*10eadc25SFrank Rowand before running. 292*10eadc25SFrank Rowand 293*10eadc25SFrank Rowand If \${KBUILD_OUTPUT} is a relative path, then '-s SRCDIR', -S, or run 294*10eadc25SFrank Rowand this script from the root of the Linux kernel source tree is required. 295*10eadc25SFrank Rowand 296*10eadc25SFrank Rowand Fallback '${__DTC}' was also not in \${PATH} or is not executable. 297*10eadc25SFrank Rowand 298*10eadc25SFrank Rowandeod 299*10eadc25SFrank Rowand exit 2 300*10eadc25SFrank Rowand fi 301*10eadc25SFrank Rowand DTC=${__DTC} 302*10eadc25SFrank Rowandfi 303*10eadc25SFrank Rowand 304*10eadc25SFrank Rowand 305*10eadc25SFrank Rowand# ----- cpp and dtc flags same as for linux source tree build of .dtb files, 306*10eadc25SFrank Rowand# plus directories of the dtx file(s) 307*10eadc25SFrank Rowand 308*10eadc25SFrank Rowanddtx_path_1_dtc_include="-i `dirname ${dtx_file_1}`" 309*10eadc25SFrank Rowand 310*10eadc25SFrank Rowanddtx_path_2_dtc_include="" 311*10eadc25SFrank Rowandif (( ${cmd_diff} )) ; then 312*10eadc25SFrank Rowand dtx_path_2_dtc_include="-i `dirname ${dtx_file_2}`" 313*10eadc25SFrank Rowandfi 314*10eadc25SFrank Rowand 315*10eadc25SFrank Rowandcpp_flags="\ 316*10eadc25SFrank Rowand -nostdinc \ 317*10eadc25SFrank Rowand -I${srctree}/arch/${ARCH}/boot/dts \ 318*10eadc25SFrank Rowand -I${srctree}/arch/${ARCH}/boot/dts/include \ 319*10eadc25SFrank Rowand -I${srctree}/drivers/of/testcase-data \ 320*10eadc25SFrank Rowand -undef -D__DTS__" 321*10eadc25SFrank Rowand 322*10eadc25SFrank Rowanddtc_flags="\ 323*10eadc25SFrank Rowand -i ${srctree}/arch/${ARCH}/boot/dts/ \ 324*10eadc25SFrank Rowand -i ${srctree}/kernel/dts \ 325*10eadc25SFrank Rowand ${dtx_path_1_dtc_include} \ 326*10eadc25SFrank Rowand ${dtx_path_2_dtc_include}" 327*10eadc25SFrank Rowand 328*10eadc25SFrank RowandDTC="${DTC} ${dtc_flags} -O dts -qq -f ${dtc_sort} -o -" 329*10eadc25SFrank Rowand 330*10eadc25SFrank Rowand 331*10eadc25SFrank Rowand# ----- do the diff or decompile 332*10eadc25SFrank Rowand 333*10eadc25SFrank Rowandif (( ${cmd_diff} )) ; then 334*10eadc25SFrank Rowand 335*10eadc25SFrank Rowand diff ${diff_flags} \ 336*10eadc25SFrank Rowand <(compile_to_dts "${dtx_file_1}") \ 337*10eadc25SFrank Rowand <(compile_to_dts "${dtx_file_2}") 338*10eadc25SFrank Rowand 339*10eadc25SFrank Rowandelse 340*10eadc25SFrank Rowand 341*10eadc25SFrank Rowand compile_to_dts "${dtx_file_1}" 342*10eadc25SFrank Rowand 343*10eadc25SFrank Rowandfi 344