Back to home page

OSCL-LXR

 
 

    


0001 #! /bin/bash
0002 # SPDX-License-Identifier: GPL-2.0-only
0003 
0004 # Copyright (C) 2015 Frank Rowand
0005 #
0006 
0007 
0008 usage() {
0009 
0010         # use spaces instead of tabs in the usage message
0011         cat >&2 <<eod
0012 
0013 Usage:
0014 
0015    `basename $0` DTx
0016         decompile DTx
0017 
0018    `basename $0` DTx_1 DTx_2
0019         diff DTx_1 and DTx_2
0020 
0021 
0022       --annotate    synonym for -T
0023       --color       synonym for -c (requires diff with --color support)
0024        -c           enable colored output
0025        -f           print full dts in diff (--unified=99999)
0026        -h           synonym for --help
0027        -help        synonym for --help
0028       --help        print this message and exit
0029        -s SRCTREE   linux kernel source tree is at path SRCTREE
0030                         (default is current directory)
0031        -S           linux kernel source tree is at root of current git repo
0032        -T           annotate output .dts with input source file and line
0033                         (-T -T for more details)
0034        -u           unsorted, do not sort DTx
0035 
0036 
0037 Each DTx is processed by the dtc compiler to produce a sorted dts source
0038 file.  If DTx is a dts source file then it is pre-processed in the same
0039 manner as done for the compile of the dts source file in the Linux kernel
0040 build system ('#include' and '/include/' directives are processed).
0041 
0042 If two DTx are provided, the resulting dts source files are diffed.
0043 
0044 If DTx is a directory, it is treated as a DT subtree, such as
0045   /proc/device-tree.
0046 
0047 If DTx contains the binary blob magic value in the first four bytes,
0048   it is treated as a binary blob (aka .dtb or FDT).
0049 
0050 Otherwise DTx is treated as a dts source file (aka .dts).
0051 
0052    If this script is not run from the root of the linux source tree,
0053    and DTx utilizes '#include' or '/include/' then the path of the
0054    linux source tree can be provided by '-s SRCTREE' or '-S' so that
0055    include paths will be set properly.
0056 
0057    The shell variable \${ARCH} must provide the architecture containing
0058    the dts source file for include paths to be set properly for '#include'
0059    or '/include/' to be processed.
0060 
0061    If DTx_1 and DTx_2 are in different architectures, then this script
0062    may not work since \${ARCH} is part of the include path.  The following
0063    workaround can be used:
0064 
0065       `basename $0` ARCH=arch_of_dtx_1 DTx_1 >tmp_dtx_1.dts
0066       `basename $0` ARCH=arch_of_dtx_2 DTx_2 >tmp_dtx_2.dts
0067       `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
0068       rm tmp_dtx_1.dts tmp_dtx_2.dts
0069 
0070    If DTx_1 and DTx_2 are in different directories, then this script will
0071    add the path of DTx_1 and DTx_2 to the include paths.  If DTx_2 includes
0072    a local file that exists in both the path of DTx_1 and DTx_2 then the
0073    file in the path of DTx_1 will incorrectly be included.  Possible
0074    workaround:
0075 
0076       `basename $0` DTx_1 >tmp_dtx_1.dts
0077       `basename $0` DTx_2 >tmp_dtx_2.dts
0078       `basename $0` tmp_dtx_1.dts tmp_dtx_2.dts
0079       rm tmp_dtx_1.dts tmp_dtx_2.dts
0080 
0081 eod
0082 }
0083 
0084 
0085 compile_to_dts() {
0086 
0087         dtx="$1"
0088         dtc_include="$2"
0089 
0090         if [ -d "${dtx}" ] ; then
0091 
0092                 # -----  input is file tree
0093 
0094                 if ( ! ${DTC} -I fs ${dtx} ) ; then
0095                         exit 3
0096                 fi
0097 
0098         elif [ -f "${dtx}" ] && [ -r "${dtx}" ] ; then
0099 
0100                 magic=`hexdump -n 4 -e '/1 "%02x"' ${dtx}`
0101                 if [ "${magic}" = "d00dfeed" ] ; then
0102 
0103                         # -----  input is FDT (binary blob)
0104 
0105                         if ( ! ${DTC} -I dtb ${dtx} ) ; then
0106                                 exit 3
0107                         fi
0108 
0109                         return
0110 
0111                 fi
0112 
0113                 # -----  input is DTS (source)
0114 
0115                 if ( cpp ${cpp_flags} -x assembler-with-cpp ${dtx} \
0116                         | ${DTC} ${dtc_include} -I dts ) ; then
0117                         return
0118                 fi
0119 
0120                 echo ""                                                      >&2
0121                 echo "Possible hints to resolve the above error:"            >&2
0122                 echo "  (hints might not fix the problem)"                   >&2
0123 
0124                 hint_given=0
0125 
0126                 if [ "${ARCH}" = "" ] ; then
0127                         hint_given=1
0128                         echo ""                                              >&2
0129                         echo "  shell variable \$ARCH not set"               >&2
0130                 fi
0131 
0132                 dtx_arch=`echo "/${dtx}" | sed -e 's|.*/arch/||' -e 's|/.*||'`
0133 
0134                 if [ "${dtx_arch}" != ""  -a "${dtx_arch}" != "${ARCH}" ] ; then
0135                         hint_given=1
0136                         echo ""                                              >&2
0137                         echo "  architecture ${dtx_arch} is in file path,"   >&2
0138                         echo "  but does not match shell variable \$ARCH"    >&2
0139                         echo "  >>\$ARCH<< is: >>${ARCH}<<"                  >&2
0140                 fi
0141 
0142                 if [ ! -d ${srctree}/arch/${ARCH} ] ; then
0143                         hint_given=1
0144                         echo ""                                              >&2
0145                         echo "  ${srctree}/arch/${ARCH}/ does not exist"     >&2
0146                         echo "  Is \$ARCH='${ARCH}' correct?"                >&2
0147                         echo "  Possible fix: use '-s' option"               >&2
0148 
0149                         git_root=`git rev-parse --show-toplevel 2>/dev/null`
0150                         if [ -d ${git_root}/arch/ ] ; then
0151                                 echo "  Possible fix: use '-S' option"       >&2
0152                         fi
0153                 fi
0154 
0155                 if [ $hint_given = 0 ] ; then
0156                         echo ""                                              >&2
0157                         echo "  No hints available."                         >&2
0158                 fi
0159 
0160                 echo ""                                                      >&2
0161 
0162                 exit 3
0163 
0164         else
0165                 echo ""                                                     >&2
0166                 echo "ERROR: ${dtx} does not exist or is not readable"      >&2
0167                 echo ""                                                     >&2
0168                 exit 2
0169         fi
0170 
0171 }
0172 
0173 
0174 # -----  start of script
0175 
0176 annotate=""
0177 cmd_diff=0
0178 diff_flags="-u"
0179 diff_color=""
0180 dtx_file_1=""
0181 dtx_file_2=""
0182 dtc_sort="-s"
0183 help=0
0184 srctree=""
0185 
0186 
0187 while [ $# -gt 0 ] ; do
0188 
0189         case $1 in
0190 
0191         -c | --color )
0192                 if diff --color /dev/null /dev/null 2>/dev/null ; then
0193                         diff_color="--color=always"
0194                 fi
0195                 shift
0196                 ;;
0197 
0198         -f )
0199                 diff_flags="--unified=999999"
0200                 shift
0201                 ;;
0202 
0203         -h | -help | --help )
0204                 help=1
0205                 shift
0206                 ;;
0207 
0208         -s )
0209                 srctree="$2"
0210                 shift 2
0211                 ;;
0212 
0213         -S )
0214                 git_root=`git rev-parse --show-toplevel 2>/dev/null`
0215                 srctree="${git_root}"
0216                 shift
0217                 ;;
0218 
0219         -T | --annotate )
0220                 if [ "${annotate}"  = "" ] ; then
0221                         annotate="-T"
0222                 elif [ "${annotate}"  = "-T" ] ; then
0223                         annotate="-T -T"
0224                 fi
0225                 shift
0226                 ;;
0227         -u )
0228                 dtc_sort=""
0229                 shift
0230                 ;;
0231 
0232         *)
0233                 if [ "${dtx_file_1}"  = "" ] ; then
0234                         dtx_file_1="$1"
0235                 elif [ "${dtx_file_2}" = "" ] ; then
0236                         dtx_file_2="$1"
0237                 else
0238                         echo ""                                             >&2
0239                         echo "ERROR: Unexpected parameter: $1"              >&2
0240                         echo ""                                             >&2
0241                         exit 2
0242                 fi
0243                 shift
0244                 ;;
0245 
0246         esac
0247 
0248 done
0249 
0250 if [ "${srctree}" = "" ] ; then
0251         srctree="."
0252 fi
0253 
0254 if [ "${dtx_file_2}" != "" ]; then
0255         cmd_diff=1
0256 fi
0257 
0258 if (( ${help} )) ; then
0259         usage
0260         exit 1
0261 fi
0262 
0263 # this must follow check for ${help}
0264 if [ "${dtx_file_1}" = "" ]; then
0265         echo ""                                                             >&2
0266         echo "ERROR: parameter DTx required"                                >&2
0267         echo ""                                                             >&2
0268         exit 2
0269 fi
0270 
0271 
0272 # -----  prefer dtc from linux kernel, allow fallback to dtc in $PATH
0273 
0274 if [ "${KBUILD_OUTPUT:0:2}" = ".." ] ; then
0275         __KBUILD_OUTPUT="${srctree}/${KBUILD_OUTPUT}"
0276 elif [ "${KBUILD_OUTPUT}" = "" ] ; then
0277         __KBUILD_OUTPUT="."
0278 else
0279         __KBUILD_OUTPUT="${KBUILD_OUTPUT}"
0280 fi
0281 
0282 DTC="${__KBUILD_OUTPUT}/scripts/dtc/dtc"
0283 
0284 if [ ! -x ${DTC} ] ; then
0285         __DTC="dtc"
0286         if grep -q "^CONFIG_DTC=y" ${__KBUILD_OUTPUT}/.config 2>/dev/null; then
0287                 make_command='
0288          make scripts'
0289         else
0290                 make_command='
0291          Enable CONFIG_DTC in the kernel configuration
0292          make scripts'
0293         fi
0294         if ( ! which ${__DTC} >/dev/null ) ; then
0295 
0296                 # use spaces instead of tabs in the error message
0297                 cat >&2 <<eod
0298 
0299 ERROR: unable to find a 'dtc' program
0300 
0301    Preferred 'dtc' (built from Linux kernel source tree) was not found or
0302    is not executable.
0303 
0304       'dtc' is: ${DTC}
0305 
0306       If it does not exist, create it from the root of the Linux source tree:
0307 ${make_command}
0308 
0309       If not at the root of the Linux kernel source tree -s SRCTREE or -S
0310       may need to be specified to find 'dtc'.
0311 
0312       If 'O=\${dir}' is specified in your Linux builds, this script requires
0313       'export KBUILD_OUTPUT=\${dir}' or add \${dir}/scripts/dtc to \$PATH
0314       before running.
0315 
0316       If \${KBUILD_OUTPUT} is a relative path, then '-s SRCDIR', -S, or run
0317       this script from the root of the Linux kernel source tree is required.
0318 
0319    Fallback '${__DTC}' was also not in \${PATH} or is not executable.
0320 
0321 eod
0322                 exit 2
0323         fi
0324         DTC=${__DTC}
0325 fi
0326 
0327 
0328 # -----  cpp and dtc flags same as for linux source tree build of .dtb files,
0329 #        plus directories of the dtx file(s)
0330 
0331 dtx_path_1_dtc_include="-i `dirname ${dtx_file_1}`"
0332 
0333 dtx_path_2_dtc_include=""
0334 if (( ${cmd_diff} )) ; then
0335         dtx_path_2_dtc_include="-i `dirname ${dtx_file_2}`"
0336 fi
0337 
0338 cpp_flags="\
0339         -nostdinc                                  \
0340         -I${srctree}/scripts/dtc/include-prefixes  \
0341         -undef -D__DTS__"
0342 
0343 DTC="\
0344         ${DTC}                                     \
0345         -i ${srctree}/scripts/dtc/include-prefixes \
0346         -O dts -qq -f ${dtc_sort} ${annotate} -o -"
0347 
0348 
0349 # -----  do the diff or decompile
0350 
0351 if (( ${cmd_diff} )) ; then
0352 
0353         diff ${diff_flags} ${diff_color} --label "${dtx_file_1}" --label "${dtx_file_2}" \
0354                 <(compile_to_dts "${dtx_file_1}" "${dtx_path_1_dtc_include}") \
0355                 <(compile_to_dts "${dtx_file_2}" "${dtx_path_2_dtc_include}")
0356 
0357 else
0358 
0359         compile_to_dts "${dtx_file_1}" "${dtx_path_1_dtc_include}"
0360 
0361 fi