treewide: Move device_tree to commonlib
[coreboot2.git] / util / find_usbdebug / find_usbdebug.sh
blob53b9a7f8f2c7c8c337dee781c5f4cb47db511280
1 #!/usr/bin/env bash
3 # SPDX-License-Identifier: GPL-2.0-only
5 LANG=C
6 # Some tools emit errors that don't matter (bugs in lspci/PCI firmware and lsusb).
7 # To shown them anyway (e.g. for debugging) comment next line.
8 exec 2>/dev/null
10 if [ "$1" = "-h" ]; then
11 printf "Usage: $0 [-h | path to dmesg log]
13 This script tries to find USB ports compatible with USB2/EHCI debug devices and
14 helps you to find their physical locations. To that end, attach at least one
15 uniquely identifiable device to a USB port and run this script. The device needs
16 to be visible in the output of \"lsusb -t\" (debug devices are often *not*!).
18 After determining compatibility of the USB controllers the script will print the
19 devices attached to the debug port as shown by lsusb. If nothing shows up simply
20 switch ports and repeat the process.
22 Note: usually only one port is supported for debugging.\n"
23 exit 0
25 uid=`id -u`
26 if [ "$uid" -ne 0 ]; then
27 echo "Must be run as root. Exiting."
28 exit 1
30 dmesgfile=$1
32 find_devs_in_tree () {
33 bus=$1
34 port=$2
35 busstr=`printf "Bus %02d" "$bus"`
36 portstr="Port $port"
38 hubs_to_ignore="8087:0020 8087:0024"
39 reqlvl=1
41 found=
42 # Iterate over the output of lsusb -t because it contains the physical port numbers
43 while IFS='' read -r line; do
44 # We need to keep track of the current bus "branch"
45 # Look out for lines starting with /: (that indicate a bus)
46 if [ "${line#*/:}" != "$line" ]; then
47 if [ "${line#*$busstr}" != "$line" ]; then
48 cur_bus=$busstr
49 else
50 cur_bus=
52 continue
55 # Skip all lines not belonging to the wanted bus number
56 if [ "$cur_bus" != "$busstr" ]; then
57 continue
60 # Calculate current USB tier/level
61 spaces="${line%%[!' ']*}"
62 curlvl=$((${#spaces} / 4))
63 if [ $curlvl -ne $reqlvl ]; then
64 continue
67 # Fetch USB IDs of the current device
68 dev=`echo ${line#*Dev } | cut -d ',' -f 1`
69 lsusbline=`lsusb -s "$bus":"$dev"`
70 if [[ ! "$lsusbline" =~ .*([[:xdigit:]]{4}:[[:xdigit:]]{4}) ]]; then
71 printf "Unexpected output from \"%s\": \"%s\"\n" "lsusb -s $bus:$dev" "$usbline"
72 exit 1
74 ids=${BASH_REMATCH[1]}
76 # Skip over rate matching hubs
77 if [[ "$hubs_to_ignore" == *"$ids"* ]]; then
78 ((reqlvl += 1))
79 continue
82 # Check for matching physical USB port
83 if [ "${line#*$portstr}" != "$line" ]; then
84 echo "$lsusbline"
85 return
87 done<< EOF
88 $(lsusb -t)
89 EOF
90 if [ -z "$found" ]; then
91 echo "none"
95 debug_lspci_devs=`lspci -nvvD |
96 grep -i "^[0-9a-f]\|debug port" |
97 grep -iB1 --no-group-separator "debug port" |
98 grep -vi "debug port" |
99 cut -f 1 -d" " |
100 sort |
101 xargs echo`
103 if [ -z "$debug_lspci_devs" ]; then
104 printf "No USB controller with debug capability found by lspci.\n
105 Possible reasons: lspci too old, USB controller does not support a debug device, ... Exiting.\n"
106 exit 1
108 printf "The following PCI devices support a USB debug port (says lspci): $debug_lspci_devs\n"
110 debug_dmesg_devs_with_port=`( test -z "$dmesgfile" &&
111 dmesg ||
112 cat "$dmesgfile") |
113 grep -i "ehci.*debug port" |
114 sed "s/.* \([0-9a-f]*:*[0-9a-f]\{2\}:[0-9a-f]\{2\}\.[0-9a-f]\).*ebug port /\1 /" |
115 sort`
117 debug_dmesg_devs=`echo "$debug_dmesg_devs_with_port" |
118 cut -f 1 -d" " |
119 xargs echo`
121 if [ -z "$debug_dmesg_devs" ]; then
122 printf "dmesg does not show any supported ports.\n
123 Possible reasons: dmesg scrolled off, kernel too old, USB controller does not support a debug device, ... Exiting.\n
124 Note: You can specify a file containing kernel messages as an argument to this program (e.g. /var/log/dmesg)."
125 exit 1
128 if [ "$debug_lspci_devs" != "$debug_dmesg_devs" ]; then
129 echo "lspci and the kernel do not agree on USB debug device support. Exiting."
130 exit 1
133 printf "and the kernel agrees, good.\n\n"
135 while true; do
136 for dev in $debug_dmesg_devs; do
137 bus=`lsusb -v |
138 grep "^Bus\|iSerial.*" |
139 grep -B1 --no-group-separator "iSerial.*$dev" |
140 grep "^Bus" |
141 sed "s/Bus *0*\([0-9a-f]*\).*/\1/"`
142 port=`echo "$debug_dmesg_devs_with_port" |
143 grep "^$dev" |
144 cut -f 2 -d" "`
146 echo "Device(s) currently connected to the debug-capable port $port on PCI device $dev, USB bus $bus:"
148 find_devs_in_tree "$bus" "$port"
149 echo
150 done
152 echo "Enter 'q' to abort or anything else to repeat"
153 read -r r
154 if [ $? -ne 0 -o "$r" = "q" ]; then
155 break;
157 done
159 exit 0