dtx_diff 8.9 KB

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