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 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
|
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (C) 2015 Frank Rowand
#
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
--annotate synonym for -T
--color synonym for -c (requires diff with --color support)
-c enable colored output
-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
-T annotate output .dts with input source file and line
(-T -T for more details)
-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. The following
workaround can be used:
`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
annotate=""
cmd_diff=0
diff_flags="-u"
diff_color=""
dtx_file_1=""
dtx_file_2=""
dtc_sort="-s"
help=0
srctree=""
while [ $# -gt 0 ] ; do
case $1 in
-c | --color )
if diff --color /dev/null /dev/null 2>/dev/null ; then
diff_color="--color=always"
fi
shift
;;
-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
;;
-T | --annotate )
if [ "${annotate}" = "" ] ; then
annotate="-T"
elif [ "${annotate}" = "-T" ] ; then
annotate="-T -T"
fi
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} ${annotate} -o -"
# ----- do the diff or decompile
if (( ${cmd_diff} )) ; then
diff ${diff_flags} ${diff_color} --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
|