123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- #!/usr/bin/env bash
- set -e
- all_components=(
- "dmi"
- "dmesg"
- "acpidump"
- "acpi"
- "platform"
- "serial"
- "sam"
- "kconfig"
- "lspci"
- "lsusb"
- )
- # commands-line interface
- print_help () {
- pname="$(basename "${0}")"
- echo "${pname} - Linux Surface diagnostics tool"
- echo ""
- echo "Collects diagnostics information for Microsoft Surface devices running Linux."
- echo ""
- echo "USAGE:"
- echo " ${pname} [FLAGS...] COMPONENTS..."
- echo ""
- echo "FLAGS:"
- echo " -h, --help Prints this help message"
- echo " -o, --output FILE The gzip archive to write to [default: diagnostics.tar.gz]"
- echo ""
- echo "COMPONENTS:"
- echo " Space-separated list of components or 'full' for all components."
- echo ""
- echo " Available components are:"
- for c in "${all_components[@]}"; do
- echo " ${c}"
- done
- echo ""
- echo "Examples:"
- echo " ${pname} --help Print this help message"
- echo " ${pname} full Collect full suite of diagnostics"
- echo " ${pname} dmi acpidump Collect only DMI information and ACPI dump"
- }
- components=()
- archive="diagnostics.tar.gz"
- while [[ ${#} -gt 0 ]]; do
- key="${1}"
- case "${key}" in
- -h|--help)
- print_help
- exit
- ;;
- -o|--output)
- if [[ ${#} -lt 2 ]]; then
- echo "Error: Missing argument for option '${1}'"
- echo " Run with '--help' for more information."
- exit 1
- fi
- archive="${2}"
- if [[ "${archive}" != *".tar.gz" ]]; then
- echo "Error: Invalid file ending for output archive, should be '.tar.gz'."
- exit 1
- fi
- shift 2
- ;;
- *)
- components+=("${1}")
- shift
- ;;
- esac
- done
- # ensure some component is selected
- if [[ ${#components[@]} -eq 0 ]]; then
- echo "Error: No component selected"
- echo " Run with '--help' for more information."
- exit 1
- fi
- # handle special component names
- if [[ " ${components[*]} " =~ " full " ]]; then
- components=("${all_components[@]}")
- fi
- # validate component list
- for c in "${components[@]}"; do
- if [[ ! " ${all_components[*]} " =~ " ${c} " ]]; then
- echo "Error: Unknown component '${c}'"
- echo " Run with '--help' for more information."
- exit 1
- fi
- done;
- # set up temporary directory
- tmpdir=""
- on_exit () {
- # remove temporary directory if set
- if [[ -n "${tmpdir}" ]]; then
- rm -rf "${tmpdir}"
- fi
- }
- trap on_exit EXIT
- tmpdir="$(mktemp -d -t "surface-diagnostics.XXXXXX")"
- # collect information
- timestamp=$(date --iso-8601=seconds)
- collect_sysfs () {
- subsystem="${1}"
- if [[ -d "/sys/bus/${subsystem}/" ]]; then
- tree -l -L 3 "/sys/bus/${subsystem}/drivers/" > "${tmpdir}/sys-bus-${subsystem}-drivers.txt"
- tree -l -L 3 "/sys/bus/${subsystem}/devices/" > "${tmpdir}/sys-bus-${subsystem}-devices.txt"
- else
- echo "<subsystem not available>" > "${tmpdir}/sys-bus-${subsystem}-drivers.txt"
- echo "<subsystem not available>" > "${tmpdir}/sys-bus-${subsystem}-devices.txt"
- fi
- }
- # collect timestamp and uname
- echo " ==> collecting information..."
- echo "${timestamp}" > "${tmpdir}/timestamp"
- echo " - uname"
- uname -a > "${tmpdir}/uname"
- # collect DMI if specified
- if [[ " ${components[*]} " =~ " dmi " ]]; then
- echo " - DMI system information"
- sudo dmidecode -t system > "${tmpdir}/dmi-system.txt"
- fi
- # collect dmesg log if specified
- if [[ " ${components[*]} " =~ " dmesg " ]]; then
- echo " - dmesg log"
- sudo dmesg > "${tmpdir}/dmesg.log"
- fi
- # collect acpidump if specified
- if [[ " ${components[*]} " =~ " acpidump " ]]; then
- echo " - ACPI dump"
- sudo acpidump | perl -pe 'BEGIN{undef $/;} s|MSDM.*?\n\n||sgm' > "${tmpdir}/acpidump.txt"
- fi
- # collect acpi sysfs entries and device paths if specified
- if [[ " ${components[*]} " =~ " acpi " ]]; then
- echo " - ACPI device information and paths (sysfs)"
- collect_sysfs "acpi"
- grep ".*" "/sys/bus/acpi/devices/"*"/path" > "${tmpdir}/sys-bus-acpi-devices.paths.txt"
- fi
- # collect platform sysfs entries
- if [[ " ${components[*]} " =~ " platform " ]]; then
- echo " - platform device information (sysfs)"
- collect_sysfs "platform"
- fi
- # collect serial sysfs entries
- if [[ " ${components[*]} " =~ " serial " ]]; then
- echo " - serial/UART device information (sysfs)"
- collect_sysfs "serial"
- fi
- # collect SAM information
- if [[ " ${components[*]} " =~ " sam " ]]; then
- echo " - surface aggregator module information (sysfs)"
- collect_sysfs "surface_aggregator"
- # get SAM firmware version
- out="${tmpdir}/sam-firmware-version"
- if [[ ! -d "/sys/bus/acpi/devices/MSHW0084:00/" ]]; then
- echo "<MSHW0084:00 does not exist>" > "${out}"
- elif [[ ! -d "/sys/bus/acpi/devices/MSHW0084:00/physical_node" ]]; then
- echo "<MSHW0084:00 does not have a physical node>" > "${out}"
- elif [[ ! -d "/sys/bus/acpi/devices/MSHW0084:00/physical_node/sam" ]]; then
- echo "<MSHW0084:00 physical node does not have SAM attributes>" > "${out}"
- else
- cat "/sys/bus/acpi/devices/MSHW0084:00/physical_node/sam/firmware_version" > "${out}"
- fi
- fi
- # collect kernel config
- if [[ " ${components[*]} " =~ " kconfig " ]]; then
- echo " - kernel configuration"
- # attempt to load module for accessing current kernel config
- if modinfo configs > /dev/null 2>&1; then
- sudo modprobe configs
- fi
- # try to get current config from /proc, if available
- if [[ -f "/proc/config.gz" ]]; then
- zcat "/proc/config.gz" > "${tmpdir}/kernel-$(uname -r).conf"
- fi
- # try to get current config from /boot, if available
- if [[ -f "/boot/config" ]]; then
- cp "/boot/config" "${tmpdir}/kernel-$(uname -r).conf"
- fi
- # try to get any config from /boot
- find "/boot" -name 'config-*' -print0 | while IFS= read -r -d '' file; do
- name="$(basename "${file}")"
- cp "${file}" "${tmpdir}/kernel-${name#"config-"}.conf"
- done;
- fi
- # collect lspci
- if [[ " ${components[*]} " =~ " lspci " ]]; then
- echo " - lspci"
- sudo lspci -nn -vvv > "${tmpdir}/lspci.txt"
- sudo lspci -nn -v -t > "${tmpdir}/lspci-tree.txt"
- fi
- # collect lsusb
- if [[ " ${components[*]} " =~ " lsusb " ]]; then
- echo " - lsusb"
- sudo lsusb -v > "${tmpdir}/lsusb.txt"
- sudo lsusb -v -t > "${tmpdir}/lsusb-tree.txt"
- fi
- # bundle to archive
- echo " ==> generating archive..."
- tar -czf "./${archive}" -C "${tmpdir}" .
- echo " ==> done"
- echo ""
- echo "Please post the generated '${archive}' file."
|