utils: introduce find_usbdebug.sh to help find USB debug ports

Carl-Daniel made this script a long time ago but it never was picked up
in the tree. Now that USB debugging is way more common it makes
sense to include it.

I have made a number of changes to the original version:
* -h help text
* check for running as root
* enhanced readability (test -> if)
* new execution flow and refined output that better shows the device(s)
  attached to the debug port(s)
* handling of Intel rate-matching hubs
* hiding of (bogus) error messages from lspci and lsusb

Signed-off-by: Stefan Tauner <stefan.tauner@gmx.at>
Change-Id: Iadf775e990f5c5f91a28d57e3331d1f59acee305
Reviewed-on: https://review.coreboot.org/c/9305
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Stefan Tauner 2016-05-02 23:16:57 +02:00 committed by Patrick Georgi
parent 43825e8960
commit 47d6663bba
4 changed files with 172 additions and 0 deletions

View File

@ -40,6 +40,7 @@ _coreboot.org-status_ and _docs.coreboot.org_
Controller (EC). `C`
* __exynos__ - Computes and fills Exynos ROM checksum (for BL1 or BL2).
`Python2`
* __find_usbdebug__ - Help find USB debug ports
* __futility__ - Firmware utility for signing ChromeOS images `Make`
* __fuzz-tests__ - Create test cases that crash the jpeg code. `C`
* __genbuild_h__ - Generate build system definitions `Shell`

View File

@ -38,6 +38,7 @@ _coreboot.org-status_ and _docs.coreboot.org_
Controller (EC). `C`
* __exynos__ - Computes and fills Exynos ROM checksum (for BL1 or BL2).
`Python2`
* __find_usbdebug__ - Help find USB debug ports
* __futility__ - Firmware utility for signing ChromeOS images `Make`
* __fuzz-tests__ - Create test cases that crash the jpeg code. `C`
* __genbuild_h__ - Generate build system definitions `Shell`

View File

@ -0,0 +1 @@
Help find USB debug ports

View File

@ -0,0 +1,169 @@
#!/bin/bash
# Copyright 2008 Carl-Daniel Hailfinger
# Copyright 2015 Stefan Tauner
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
LANG=C
# Some tools emit errors that don't matter (bugs in lspci/PCI firmware and lsusb).
# To shown them anyway (e.g. for debugging) comment next line.
exec 2>/dev/null
if [ "$1" = "-h" ]; then
printf "Usage: $0 [-h | path to dmesg log]
This script tries to find USB ports compatible with USB2/EHCI debug devices and
helps you to find their physical locations. To that end, attach at least one
uniquely identifiable device to a USB port and run this script. The device needs
to be visible in the output of \"lsusb -t\" (debug devices are often *not*!).
After determining compatibility of the USB controllers the script will print the
devices attached to the debug port as shown by lsusb. If nothing shows up simply
switch ports and repeat the process.
Note: usually only one port is supported for debugging.\n"
exit 0
fi
uid=`id -u`
if [ "$uid" -ne 0 ]; then
echo "Must be run as root. Exiting."
exit 1
fi
dmesgfile=$1
find_devs_in_tree () {
bus=$1
port=$2
busstr=`printf "Bus %02d" "$bus"`
portstr="Port $port"
hubs_to_ignore="8087:0020 8087:0024"
reqlvl=1
found=
# Iterate over the output of lsusb -t because it contains the physical port numbers
while IFS='' read -r line; do
# We need to keep track of the current bus "branch"
# Look out for lines starting with /: (that indicate a bus)
if [ "${line#*/:}" != "$line" ]; then
if [ "${line#*$busstr}" != "$line" ]; then
cur_bus=$busstr
else
cur_bus=
fi
continue
fi
# Skip all lines not belonging to the wanted bus number
if [ "$cur_bus" != "$busstr" ]; then
continue
fi
# Calculate current USB tier/level
spaces="${line%%[!' ']*}"
curlvl=$((${#spaces} / 4))
if [ $curlvl -ne $reqlvl ]; then
continue
fi
# Fetch USB IDs of the current device
dev=`echo ${line#*Dev } | cut -d ',' -f 1`
lsusbline=`lsusb -s "$bus":"$dev"`
if [[ ! "$lsusbline" =~ .*([[:xdigit:]]{4}:[[:xdigit:]]{4}) ]]; then
printf "Unexpected output from \"%s\": \"%s\"\n" "lsusb -s $bus:$dev" "$usbline"
exit 1
fi
ids=${BASH_REMATCH[1]}
# Skip over rate matching hubs
if [[ "$hubs_to_ignore" == *"$ids"* ]]; then
((reqlvl += 1))
continue
fi
# Check for matching physical USB port
if [ "${line#*$portstr}" != "$line" ]; then
echo "$lsusbline"
return
fi
done<< EOF
$(lsusb -t)
EOF
if [ -z "$found" ]; then
echo "none"
fi
}
debug_lspci_devs=`lspci -nvvD |
grep -i "^[0-9a-f]\|debug port" |
grep -iB1 --no-group-separator "debug port" |
grep -vi "debug port" |
cut -f 1 -d" " |
sort |
xargs echo`
if [ -z "$debug_lspci_devs" ]; then
printf "No USB controller with debug capability found by lspci.\n
Possible reasons: lspci too old, USB controller does not support a debug device, ... Exiting.\n"
exit 1
fi
printf "The following PCI devices support a USB debug port (says lspci): $debug_lspci_devs\n"
debug_dmesg_devs_with_port=`( test -z "$dmesgfile" &&
dmesg ||
cat "$dmesgfile") |
grep -i "ehci.*debug port" |
sed "s/.* \([0-9a-f]*:*[0-9a-f]\{2\}:[0-9a-f]\{2\}\.[0-9a-f]\).*ebug port /\1 /" |
sort`
debug_dmesg_devs=`echo "$debug_dmesg_devs_with_port" |
cut -f 1 -d" " |
xargs echo`
if [ -z "$debug_dmesg_devs" ]; then
printf "dmesg does not show any supported ports.\n
Possible reasons: dmesg scrolled off, kernel too old, USB controller does not support a debug device, ... Exiting.\n
Note: You can specify a file containing kernel messages as an argument to this program (e.g. /var/log/dmesg)."
exit 1
fi
if [ "$debug_lspci_devs" != "$debug_dmesg_devs" ]; then
echo "lspci and the kernel do not agree on USB debug device support. Exiting."
exit 1
fi
printf "and the kernel agrees, good.\n\n"
while true; do
for dev in $debug_dmesg_devs; do
bus=`lsusb -v |
grep "^Bus\|iSerial.*" |
grep -B1 --no-group-separator "iSerial.*$dev" |
grep "^Bus" |
sed "s/Bus *0*\([0-9a-f]*\).*/\1/"`
port=`echo "$debug_dmesg_devs_with_port" |
grep "^$dev" |
cut -f 2 -d" "`
echo "Device(s) currently connected to the debug-capable port $port on PCI device $dev, USB bus $bus:"
find_devs_in_tree "$bus" "$port"
echo
done
echo "Enter 'q' to abort or anything else to repeat"
read -r r
if [ $? -ne 0 -o "$r" = "q" ]; then
break;
fi
done
exit 0