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