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