diagnostics.sh 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #!/usr/bin/env bash
  2. set -e
  3. all_components=(
  4. "dmi"
  5. "dmesg"
  6. "acpidump"
  7. "acpi"
  8. "platform"
  9. "serial"
  10. "sam"
  11. )
  12. # commands-line interface
  13. print_help () {
  14. pname="$(basename "${0}")"
  15. echo "${pname} - Linux Surface diagnostics tool"
  16. echo ""
  17. echo "Collects diagnostics information for Microsoft Surface devices running Linux."
  18. echo ""
  19. echo "USAGE:"
  20. echo " ${pname} [FLAGS...] COMPONENTS..."
  21. echo ""
  22. echo "FLAGS:"
  23. echo " -h, --help Prints this help message"
  24. echo " -o, --output FILE The gzip archive to write to [default: diagnostics.tar.gz]"
  25. echo ""
  26. echo "COMPONENTS:"
  27. echo " Space-separated list of components or 'full' for all components."
  28. echo ""
  29. echo " Available components are:"
  30. for c in "${all_components[@]}"; do
  31. echo " ${c}"
  32. done
  33. echo ""
  34. echo "Examples:"
  35. echo " ${pname} --help Print this help message"
  36. echo " ${pname} full Collect full suite of diagnostics"
  37. echo " ${pname} dmi acpidump Collect only DMI information and ACPI dump"
  38. }
  39. components=()
  40. archive="diagnostics.tar.gz"
  41. while [[ ${#} -gt 0 ]]; do
  42. key="${1}"
  43. case "${key}" in
  44. -h|--help)
  45. print_help
  46. exit
  47. ;;
  48. -o|--output)
  49. if [[ ${#} -lt 2 ]]; then
  50. echo "Error: Missing argument for option '${1}'"
  51. echo " Run with '--help' for more information."
  52. exit 1
  53. fi
  54. archive="${2}"
  55. if [[ "${archive}" != *".tar.gz" ]]; then
  56. echo "Error: Invalid file ending for output archive, should be '.tar.gz'."
  57. exit 1
  58. fi
  59. shift 2
  60. ;;
  61. *)
  62. components+=("${1}")
  63. shift
  64. ;;
  65. esac
  66. done
  67. # ensure some component is selected
  68. if [[ ${#components[@]} -eq 0 ]]; then
  69. echo "Error: No component selected"
  70. echo " Run with '--help' for more information."
  71. exit 1
  72. fi
  73. # handle special component names
  74. if [[ " ${components[*]} " =~ " full " ]]; then
  75. components=("${all_components[@]}")
  76. fi
  77. # validate component list
  78. for c in "${components[@]}"; do
  79. if [[ ! " ${all_components[*]} " =~ " ${c} " ]]; then
  80. echo "Error: Unknown component '${c}'"
  81. echo " Run with '--help' for more information."
  82. exit 1
  83. fi
  84. done;
  85. # set up temporary directory
  86. tmpdir=""
  87. on_exit () {
  88. # remove temporary directory if set
  89. if [[ -n "${tmpdir}" ]]; then
  90. rm -rf "${tmpdir}"
  91. fi
  92. }
  93. trap on_exit EXIT
  94. tmpdir="$(mktemp -d -t "surface-diagnostics.XXXXXX")"
  95. # collect information
  96. timestamp=$(date --iso-8601=seconds)
  97. collect_sysfs () {
  98. subsystem="${1}"
  99. if [[ -d "/sys/bus/${subsystem}/" ]]; then
  100. tree -l -L 3 "/sys/bus/${subsystem}/drivers/" > "${tmpdir}/sys-bus-${subsystem}-drivers.txt"
  101. tree -l -L 3 "/sys/bus/${subsystem}/devices/" > "${tmpdir}/sys-bus-${subsystem}-devices.txt"
  102. else
  103. echo "<subsystem not available>" > "${tmpdir}/sys-bus-${subsystem}-drivers.txt"
  104. echo "<subsystem not available>" > "${tmpdir}/sys-bus-${subsystem}-devices.txt"
  105. fi
  106. }
  107. # collect timestamp and uname
  108. echo " ==> collecting information..."
  109. echo "${timestamp}" > "${tmpdir}/timestamp"
  110. echo " - uname"
  111. uname -a > "${tmpdir}/uname"
  112. # collect DMI if specified
  113. if [[ " ${components[*]} " =~ " dmi " ]]; then
  114. echo " - DMI system information"
  115. sudo dmidecode -t system > "${tmpdir}/dmi-system.txt"
  116. fi
  117. # collect dmesg log if specified
  118. if [[ " ${components[*]} " =~ " dmesg " ]]; then
  119. echo " - dmesg log"
  120. sudo dmesg > "${tmpdir}/dmesg.log"
  121. fi
  122. # collect acpidump if specified
  123. if [[ " ${components[*]} " =~ " acpidump " ]]; then
  124. echo " - ACPI dump"
  125. sudo acpidump | perl -pe 'BEGIN{undef $/;} s|MSDM.*?\n\n||sgm' > "${tmpdir}/acpidump.txt"
  126. fi
  127. # collect acpi sysfs entries and device paths if specified
  128. if [[ " ${components[*]} " =~ " acpi " ]]; then
  129. echo " - ACPI device information and paths (sysfs)"
  130. collect_sysfs "acpi"
  131. grep ".*" "/sys/bus/acpi/devices/"*"/path" > "${tmpdir}/sys-bus-acpi-devices.paths.txt"
  132. fi
  133. # collect platform sysfs entries
  134. if [[ " ${components[*]} " =~ " platform " ]]; then
  135. echo " - platform device information (sysfs)"
  136. collect_sysfs "platform"
  137. fi
  138. # collect serial sysfs entries
  139. if [[ " ${components[*]} " =~ " serial " ]]; then
  140. echo " - serial/UART device information (sysfs)"
  141. collect_sysfs "serial"
  142. fi
  143. # collect SAM information
  144. if [[ " ${components[*]} " =~ " sam " ]]; then
  145. echo " - surface aggregator module information (sysfs)"
  146. collect_sysfs "surface_aggregator"
  147. # get SAM firmware version
  148. out="${tmpdir}/sam-firmware-version"
  149. if [[ ! -d "/sys/bus/acpi/devices/MSHW0084:00/" ]]; then
  150. echo "<MSHW0084:00 does not exist>" > "${out}"
  151. elif [[ ! -d "/sys/bus/acpi/devices/MSHW0084:00/physical_node" ]]; then
  152. echo "<MSHW0084:00 does not have a physical node>" > "${out}"
  153. elif [[ ! -d "/sys/bus/acpi/devices/MSHW0084:00/physical_node/sam" ]]; then
  154. echo "<MSHW0084:00 physical node does not have SAM attributes>" > "${out}"
  155. else
  156. cat "/sys/bus/acpi/devices/MSHW0084:00/physical_node/sam/firmware_version" > "${out}"
  157. fi
  158. fi
  159. # bundle to archive
  160. echo " ==> generating archive..."
  161. tar -czf "./${archive}" -C "${tmpdir}" .
  162. echo " ==> done"
  163. echo ""
  164. echo "Please post the generated '${archive}' file."