~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/dev-needs.sh

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #! /bin/sh
  2 # SPDX-License-Identifier: GPL-2.0
  3 # Copyright (c) 2020, Google LLC. All rights reserved.
  4 # Author: Saravana Kannan <saravanak@google.com>
  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                         # This weirdness is needed to work with toybox when
 59                         # using the -t option.
 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                         # if-statement treats 0 (no-error) as true
 73                         return 0
 74                 fi
 75                 i=$(($i+2))
 76         done
 77 
 78         # if-statement treats 1 (error) as false
 79         return 1
 80 }
 81 
 82 # Return 0 (no-error/true) if parent was added
 83 function add_parent() {
 84 
 85         if [ ${ALLOW_PARENTS} -eq 0 ]
 86         then
 87                 return 1
 88         fi
 89 
 90         local CON=$1
 91         # $CON could be a symlink path. So, we need to find the real path and
 92         # then go up one level to find the real parent.
 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 # Return 0 (no-error/true) if one or more suppliers were added
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                 # sync_state_only links are proxy dependencies.
125                 # They can also have cycles. So, don't follow them.
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                         # Stop at the first argument that's not an option.
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 # Do a breadth first, non-recursive tracking of suppliers. The parent is also
268 # considered a "supplier" as a device can't probe without its parent.
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         # If this is not a device with a driver, we don't care about its
281         # suppliers.
282         if [ ! -e ${CONSUMER}/driver -a ${ALLOW_NO_DRIVER} -eq 0 ]
283         then
284                 continue
285         fi
286 
287         ROOT=1
288 
289         # Add suppliers to CONSUMERS list and output the consumer details.
290         #
291         # We don't need to worry about a cycle in the dependency chain causing
292         # infinite loops. That's because the kernel doesn't allow cycles in
293         # device links unless it's a sync_state_only device link. And we ignore
294         # sync_state_only device links inside add_suppliers.
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 # Can NOT combine sort and uniq using sort -suk2 because stable sort in toybox
312 # isn't really stable.
313 dev_to_detail | sort -k2 -k1 | uniq -f 1 | sort | cut -f2-
314 
315 exit 0

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php