| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 |
|
| 6 | function help() {
|
| 7 | cat << EOF
|
| 8 | Usage: $(basename $0) [-c|-d|-m|-f] [filter options] <list of devices>
|
| 9 |
|
| 10 | This script needs to be run on the target device once it has booted to a
|
| 11 | shell.
|
| 12 |
|
| 13 | The script takes as input a list of one or more device directories under
|
| 14 | /sys/devices and then lists the probe dependency chain (suppliers and
|
| 15 | parents) of these devices. It does a breadth first search of the dependency
|
| 16 | chain, so the last entry in the output is close to the root of the
|
| 17 | dependency chain.
|
| 18 |
|
| 19 | By default it lists the full path to the devices under /sys/devices.
|
| 20 |
|
| 21 | It also takes an optional modifier flag as the first parameter to change
|
| 22 | what information is listed in the output. If the requested information is
|
| 23 | not available, the device name is printed.
|
| 24 |
|
| 25 | -c lists the compatible string of the dependencies
|
| 26 | -d lists the driver name of the dependencies that have probed
|
| 27 | -m lists the module name of the dependencies that have a module
|
| 28 | -f list the firmware node path of the dependencies
|
| 29 | -g list the dependencies as edges and nodes for graphviz
|
| 30 | -t list the dependencies as edges for tsort
|
| 31 |
|
| 32 | The filter options provide a way to filter out some dependencies:
|
| 33 | --allow-no-driver By default dependencies that don't have a driver
|
| 34 | attached are ignored. This is to avoid following
|
| 35 | device links to "class" devices that are created
|
| 36 | when the consumer probes (as in, not a probe
|
| 37 | dependency). If you want to follow these links
|
| 38 | anyway, use this flag.
|
| 39 |
|
| 40 | --exclude-devlinks Don't follow device links when tracking probe
|
| 41 | dependencies.
|
| 42 |
|
| 43 | --exclude-parents Don't follow parent devices when tracking probe
|
| 44 | dependencies.
|
| 45 |
|
| 46 | EOF
|
| 47 | }
|
| 48 |
|
| 49 | function dev_to_detail() {
|
| 50 | local i=0
|
| 51 | while [ $i -lt ${#OUT_LIST[@]} ]
|
| 52 | do
|
| 53 | local C=${OUT_LIST[i]}
|
| 54 | local S=${OUT_LIST[i+1]}
|
| 55 | local D="'$(detail_chosen $C $S)'"
|
| 56 | if [ ! -z "$D" ]
|
| 57 | then
|
| 58 | |
| 59 | |
| 60 | printf '%05u\t%s\n' ${i} "$D" | tr -d \'
|
| 61 | fi
|
| 62 | i=$((i+2))
|
| 63 | done
|
| 64 | }
|
| 65 |
|
| 66 | function already_seen() {
|
| 67 | local i=0
|
| 68 | while [ $i -lt ${#OUT_LIST[@]} ]
|
| 69 | do
|
| 70 | if [ "$1" = "${OUT_LIST[$i]}" ]
|
| 71 | then
|
| 72 | |
| 73 | return 0
|
| 74 | fi
|
| 75 | i=$(($i+2))
|
| 76 | done
|
| 77 |
|
| 78 | |
| 79 | return 1
|
| 80 | }
|
| 81 |
|
| 82 | |
| 83 | function add_parent() {
|
| 84 |
|
| 85 | if [ ${ALLOW_PARENTS} -eq 0 ]
|
| 86 | then
|
| 87 | return 1
|
| 88 | fi
|
| 89 |
|
| 90 | local CON=$1
|
| 91 | |
| 92 | |
| 93 | local PARENT=$(realpath $CON/..)
|
| 94 |
|
| 95 | while [ ! -e ${PARENT}/driver ]
|
| 96 | do
|
| 97 | if [ "$PARENT" = "/sys/devices" ]
|
| 98 | then
|
| 99 | return 1
|
| 100 | fi
|
| 101 | PARENT=$(realpath $PARENT/..)
|
| 102 | done
|
| 103 |
|
| 104 | CONSUMERS+=($PARENT)
|
| 105 | OUT_LIST+=(${CON} ${PARENT})
|
| 106 | return 0
|
| 107 | }
|
| 108 |
|
| 109 | |
| 110 | function add_suppliers() {
|
| 111 | local CON=$1
|
| 112 | local RET=1
|
| 113 |
|
| 114 | if [ ${ALLOW_DEVLINKS} -eq 0 ]
|
| 115 | then
|
| 116 | return 1
|
| 117 | fi
|
| 118 |
|
| 119 | SUPPLIER_LINKS=$(ls -1d $CON/supplier:* 2>/dev/null)
|
| 120 | for SL in $SUPPLIER_LINKS;
|
| 121 | do
|
| 122 | SYNC_STATE=$(cat $SL/sync_state_only)
|
| 123 |
|
| 124 | |
| 125 | |
| 126 | if [ "$SYNC_STATE" != '0' ]
|
| 127 | then
|
| 128 | continue
|
| 129 | fi
|
| 130 |
|
| 131 | SUPPLIER=$(realpath $SL/supplier)
|
| 132 |
|
| 133 | if [ ! -e $SUPPLIER/driver -a ${ALLOW_NO_DRIVER} -eq 0 ]
|
| 134 | then
|
| 135 | continue
|
| 136 | fi
|
| 137 |
|
| 138 | CONSUMERS+=($SUPPLIER)
|
| 139 | OUT_LIST+=(${CON} ${SUPPLIER})
|
| 140 | RET=0
|
| 141 | done
|
| 142 |
|
| 143 | return $RET
|
| 144 | }
|
| 145 |
|
| 146 | function detail_compat() {
|
| 147 | f=$1/of_node/compatible
|
| 148 | if [ -e $f ]
|
| 149 | then
|
| 150 | echo -n $(cat $f)
|
| 151 | else
|
| 152 | echo -n $1
|
| 153 | fi
|
| 154 | }
|
| 155 |
|
| 156 | function detail_module() {
|
| 157 | f=$1/driver/module
|
| 158 | if [ -e $f ]
|
| 159 | then
|
| 160 | echo -n $(basename $(realpath $f))
|
| 161 | else
|
| 162 | echo -n $1
|
| 163 | fi
|
| 164 | }
|
| 165 |
|
| 166 | function detail_driver() {
|
| 167 | f=$1/driver
|
| 168 | if [ -e $f ]
|
| 169 | then
|
| 170 | echo -n $(basename $(realpath $f))
|
| 171 | else
|
| 172 | echo -n $1
|
| 173 | fi
|
| 174 | }
|
| 175 |
|
| 176 | function detail_fwnode() {
|
| 177 | f=$1/firmware_node
|
| 178 | if [ ! -e $f ]
|
| 179 | then
|
| 180 | f=$1/of_node
|
| 181 | fi
|
| 182 |
|
| 183 | if [ -e $f ]
|
| 184 | then
|
| 185 | echo -n $(realpath $f)
|
| 186 | else
|
| 187 | echo -n $1
|
| 188 | fi
|
| 189 | }
|
| 190 |
|
| 191 | function detail_graphviz() {
|
| 192 | if [ "$2" != "ROOT" ]
|
| 193 | then
|
| 194 | echo -n "\"$(basename $2)\"->\"$(basename $1)\""
|
| 195 | else
|
| 196 | echo -n "\"$(basename $1)\""
|
| 197 | fi
|
| 198 | }
|
| 199 |
|
| 200 | function detail_tsort() {
|
| 201 | echo -n "\"$2\" \"$1\""
|
| 202 | }
|
| 203 |
|
| 204 | function detail_device() { echo -n $1; }
|
| 205 |
|
| 206 | alias detail=detail_device
|
| 207 | ALLOW_NO_DRIVER=0
|
| 208 | ALLOW_DEVLINKS=1
|
| 209 | ALLOW_PARENTS=1
|
| 210 |
|
| 211 | while [ $# -gt 0 ]
|
| 212 | do
|
| 213 | ARG=$1
|
| 214 | case $ARG in
|
| 215 | --help)
|
| 216 | help
|
| 217 | exit 0
|
| 218 | ;;
|
| 219 | -c)
|
| 220 | alias detail=detail_compat
|
| 221 | ;;
|
| 222 | -m)
|
| 223 | alias detail=detail_module
|
| 224 | ;;
|
| 225 | -d)
|
| 226 | alias detail=detail_driver
|
| 227 | ;;
|
| 228 | -f)
|
| 229 | alias detail=detail_fwnode
|
| 230 | ;;
|
| 231 | -g)
|
| 232 | alias detail=detail_graphviz
|
| 233 | ;;
|
| 234 | -t)
|
| 235 | alias detail=detail_tsort
|
| 236 | ;;
|
| 237 | --allow-no-driver)
|
| 238 | ALLOW_NO_DRIVER=1
|
| 239 | ;;
|
| 240 | --exclude-devlinks)
|
| 241 | ALLOW_DEVLINKS=0
|
| 242 | ;;
|
| 243 | --exclude-parents)
|
| 244 | ALLOW_PARENTS=0
|
| 245 | ;;
|
| 246 | *)
|
| 247 | |
| 248 | break
|
| 249 | ;;
|
| 250 | esac
|
| 251 | shift
|
| 252 | done
|
| 253 |
|
| 254 | function detail_chosen() {
|
| 255 | detail $1 $2
|
| 256 | }
|
| 257 |
|
| 258 | if [ $# -eq 0 ]
|
| 259 | then
|
| 260 | help
|
| 261 | exit 1
|
| 262 | fi
|
| 263 |
|
| 264 | CONSUMERS=($@)
|
| 265 | OUT_LIST=()
|
| 266 |
|
| 267 | |
| 268 | |
| 269 | i=0
|
| 270 | while [ $i -lt ${#CONSUMERS[@]} ]
|
| 271 | do
|
| 272 | CONSUMER=$(realpath ${CONSUMERS[$i]})
|
| 273 | i=$(($i+1))
|
| 274 |
|
| 275 | if already_seen ${CONSUMER}
|
| 276 | then
|
| 277 | continue
|
| 278 | fi
|
| 279 |
|
| 280 | |
| 281 | |
| 282 | if [ ! -e ${CONSUMER}/driver -a ${ALLOW_NO_DRIVER} -eq 0 ]
|
| 283 | then
|
| 284 | continue
|
| 285 | fi
|
| 286 |
|
| 287 | ROOT=1
|
| 288 |
|
| 289 | |
| 290 | |
| 291 | |
| 292 | |
| 293 | |
| 294 | |
| 295 | if add_suppliers ${CONSUMER}
|
| 296 | then
|
| 297 | ROOT=0
|
| 298 | fi
|
| 299 |
|
| 300 | if add_parent ${CONSUMER}
|
| 301 | then
|
| 302 | ROOT=0
|
| 303 | fi
|
| 304 |
|
| 305 | if [ $ROOT -eq 1 ]
|
| 306 | then
|
| 307 | OUT_LIST+=(${CONSUMER} "ROOT")
|
| 308 | fi
|
| 309 | done
|
| 310 |
|
| 311 | |
| 312 | |
| 313 | dev_to_detail | sort -k2 -k1 | uniq -f 1 | sort | cut -f2-
|
| 314 |
|
| 315 | exit 0
|