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