| #! /bin/sh |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # (c) 2019, Google |
| |
| progname=${0##*/} |
| NUM=XX |
| USAGE="USAGE: ${progname} [-s <serialno>] [-D] [-f [<input>]] [-F [-o <output> [-d <input>]]] |
| |
| Collect filtered /dev and /sys details, along with dmesg and probe list. |
| |
| -o <output> will drop the collection into a set of files, but will not |
| overwrite existing content. -F will overwrite. |
| |
| -D will wait for the display. |
| |
| if <output> is empty ('' or last option), will not collect dmesg or probe |
| list. If no -o option is specified, then <output> will be default of - |
| (stdout) and all pieces will go to the standard output separated by a cut |
| and snip header. If specified, <output> will contain the filtered /dev/ |
| and /sys/ dumps, <output>.probed the subset filter of just the probed drivers, |
| <output>.dmesg the kernel logs and <output>.config the uncompressed |
| /proc/config.gz. |
| |
| -d <input> will take the dropped collection specified to -o <output> and |
| produce a diff -U1 output compared against the <input>. |
| |
| -f <input> allows one to utilize the filter to an existing find /dev /sys |
| output from a device. No dmesg will be collected. |
| |
| -s <serialno> will allow one to specify a device to connect to when multiples |
| are available, otherwise will default to one available or ANDROID_SERIAL |
| environment variable. |
| |
| NB: The /dev/ and /sys/ dumps can be compared with something like a diff -U1 |
| and report a generally noiseless result so it is easy to spot the side |
| effects from one build to the next. Basically nothing else should be |
| added or removed from the differences other than the expectations, save |
| for normal noise from the dynamic nature of the kernel, thus making it |
| beneficial to run this script collection at the same point in the boot |
| process to keep noise down. |
| |
| NB: for default standard output, the probed list will be post-filter so |
| some details may be altered to make it easier to discover differences. |
| So if bus enumerations change, some of the enumerators will be replaced |
| with an '${NUM}' so that they continue to match when moved. For a |
| specified output, the <output>.probed file will retain the details." |
| |
| EMPTY="" |
| SPACE=" " |
| # A _real_ embedded tab character |
| TAB="`echo | tr '\n' '\t'`" |
| # A _real_ embedded carriage return character |
| CR="`echo | tr '\n' '\r'`" |
| # A _real_ embedded escape character |
| ESCAPE="`echo | tr '\n' '\033'`" |
| # Colours |
| RED="${ESCAPE}[38;5;196m" |
| ORANGE="${ESCAPE}[38;5;255:165:0m" |
| BLUE="${ESCAPE}[35m" |
| NORMAL="${ESCAPE}[0m" |
| |
| ## |
| ## Helper Functions |
| ## |
| |
| [ "USAGE: inFastboot |
| |
| Returns: true if device is in fastboot mode" ] |
| inFastboot() { |
| fastboot devices | |
| if [ -n "${ANDROID_SERIAL}" ]; then |
| grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null |
| else |
| wc -l | grep '^1$' >/dev/null |
| fi |
| } |
| |
| [ "USAGE: inAdb |
| |
| Returns: true if device is in adb mode" ] |
| inAdb() { |
| adb devices </dev/null | |
| grep -v -e 'List of devices attached' -e '^$' -e "[${SPACE}${TAB}]recovery\$" | |
| if [ -n "${ANDROID_SERIAL}" ]; then |
| grep "^${ANDROID_SERIAL}[${SPACE}${TAB}]" > /dev/null |
| else |
| wc -l | grep '^1$' >/dev/null |
| fi |
| } |
| |
| [ "USAGE: inRecovery |
| |
| Returns: true if device is in recovery mode" ] |
| inRecovery() { |
| local list="`adb devices | |
| grep -v -e 'List of devices attached' -e '^$'`" |
| if [ -n "${ANDROID_SERIAL}" ]; then |
| echo "${list}" | |
| grep "^${ANDROID_SERIAL}[${SPACE}${TAB}][${SPACE}${TAB}]*recovery\$" >/dev/null |
| return ${?} |
| fi |
| if echo "${list}" | wc -l | grep '^1$' >/dev/null; then |
| echo "${list}" | |
| grep "[${SPACE}${TAB}]recovery\$" >/dev/null |
| return ${?} |
| fi |
| false |
| } |
| |
| [ "USAGE: USB_DEVICE=\`usb_devnum [--next]\` |
| |
| USB_DEVICE contains cache. Update if system changes. |
| |
| Returns: the devnum for the USB_SERIAL device" ] |
| usb_devnum() { |
| if [ -n "${USB_SERIAL}" ]; then |
| local usb_device=`cat ${USB_SERIAL%/serial}/devnum 2>/dev/null | tr -d ' \t\r\n'` |
| if [ -n "${usb_device}" ]; then |
| USB_DEVICE=dev${usb_device} |
| elif [ -n "${USB_DEVICE}" -a "${1}" ]; then |
| USB_DEVICE=dev`expr ${USB_DEVICE#dev} + 1` |
| fi |
| echo "${USB_DEVICE}" |
| fi |
| } |
| |
| [ "USAGE: adb_sh <commands> </dev/stdin >/dev/stdout 2>/dev/stderr |
| |
| Returns: true if the command succeeded" ] |
| adb_sh() { |
| local args= |
| for i in "${@}"; do |
| [ -z "${args}" ] || args="${args} " |
| if [ X"${i}" != X"${i#\'}" ]; then |
| args="${args}${i}" |
| elif [ X"${i}" != X"${i#*\\}" ]; then |
| args="${args}`echo ${i} | sed 's/\\\\/\\\\\\\\/g'`" |
| elif [ X"${i}" != X"${i#* }" ]; then |
| args="${args}'${i}'" |
| elif [ X"${i}" != X"${i#*${TAB}}" ]; then |
| args="${args}'${i}'" |
| else |
| args="${args}${i}" |
| fi |
| done |
| adb shell "${args}" |
| } |
| |
| [ "USAGE: adb_su <commands> </dev/stdin >/dev/stdout 2>/dev/stderr |
| |
| Returns: true if the command running as root succeeded" ] |
| adb_su() { |
| adb_sh su root "${@}" |
| } |
| |
| [ "USAGE: get_property <prop> |
| |
| Returns the property value" ] |
| get_property() { |
| adb_sh getprop ${1} 2>/dev/null </dev/null |
| } |
| |
| [ "USAGE: format_duration [<seconds>|<seconds>s|<minutes>m|<hours>h|<days>d] |
| |
| human readable output whole seconds, whole minutes or mm:ss" ] |
| format_duration() { |
| if [ -z "${1}" ]; then |
| echo unknown |
| return |
| fi |
| local duration="${1}" |
| if [ X"${duration}" != X"${duration%s}" ]; then |
| duration=${duration%s} |
| elif [ X"${duration}" != X"${duration%m}" ]; then |
| duration=`expr ${duration%m} \* 60` |
| elif [ X"${duration}" != X"${duration%h}" ]; then |
| duration=`expr ${duration%h} \* 3600` |
| elif [ X"${duration}" != X"${duration%d}" ]; then |
| duration=`expr ${duration%d} \* 86400` |
| fi |
| local seconds=`expr ${duration} % 60` |
| local minutes=`expr \( ${duration} / 60 \) % 60` |
| local hours=`expr ${duration} / 3600` |
| if [ 0 -eq ${minutes} -a 0 -eq ${hours} ]; then |
| if [ 1 -eq ${duration} ]; then |
| echo 1 second |
| return |
| fi |
| echo ${duration} seconds |
| return |
| elif [ 60 -eq ${duration} ]; then |
| echo 1 minute |
| return |
| elif [ 0 -eq ${seconds} -a 0 -eq ${hours} ]; then |
| echo ${minutes} minutes |
| return |
| fi |
| if [ 0 -eq ${hours} ]; then |
| echo ${minutes}:`expr ${seconds} / 10``expr ${seconds} % 10` |
| return |
| fi |
| echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10` |
| } |
| |
| [ "USAGE: adb_wait [timeout] |
| |
| Returns: waits until the device has returned for adb or optional timeout" ] |
| adb_wait() { |
| local start=`date +%s` |
| local duration= |
| local ret |
| if [ -n "${1}" ]; then |
| USB_DEVICE=`usb_devnum --next` |
| duration=`format_duration ${1}` |
| echo -n ". . . waiting ${duration}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}" |
| timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null |
| ret=${?} |
| echo -n " ${CR}" |
| else |
| adb wait-for-device |
| ret=${?} |
| fi |
| USB_DEVICE=`usb_devnum` |
| if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then |
| local active_slot=`get_active_slot` |
| if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2 |
| fi |
| fi |
| local end=`date +%s` |
| local diff_time=`expr ${end} - ${start}` |
| local _print_time=${print_time} |
| if [ ${diff_time} -lt 15 ]; then |
| _print_time=false |
| fi |
| diff_time=`format_duration ${diff_time}` |
| if [ "${diff_time}" = "${duration}" ]; then |
| _print_time=false |
| fi |
| |
| local reason= |
| if inAdb; then |
| reason=`get_property ro.boot.bootreason` |
| fi |
| case ${reason} in |
| reboot*) |
| reason= |
| ;; |
| ${EMPTY}) |
| ;; |
| *) |
| reason=" for boot reason ${reason}" |
| ;; |
| esac |
| if ${_print_time} || [ -n "${reason}" ]; then |
| echo "${BLUE}[ INFO ]${NORMAL} adb wait duration ${diff_time}${reason}" |
| fi >&2 |
| |
| return ${ret} |
| } |
| |
| [ "USAGE: fastboot_wait [timeout] |
| |
| Returns: waits until the device has returned for fastboot or optional timeout" ] |
| fastboot_wait() { |
| local ret |
| # fastboot has no wait-for-device, but it does an automatic |
| # wait and requires (even a nonsensical) command to do so. |
| if [ -n "${1}" ]; then |
| USB_DEVICE=`usb_devnum --next` |
| echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}" |
| timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null |
| ret=${?} |
| echo -n " ${CR}" |
| ( exit ${ret} ) |
| else |
| fastboot wait-for-device >/dev/null 2>/dev/null |
| fi || |
| inFastboot |
| ret=${?} |
| USB_DEVICE=`usb_devnum` |
| if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then |
| local active_slot=`get_active_slot` |
| if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" |
| fi >&2 |
| fi |
| return ${ret} |
| } |
| |
| [ "USAGE: recovery_wait [timeout] |
| |
| Returns: waits until the device has returned for recovery or optional timeout" ] |
| recovery_wait() { |
| local ret |
| if [ -n "${1}" ]; then |
| USB_DEVICE=`usb_devnum --next` |
| echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}" |
| timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null |
| ret=${?} |
| echo -n " ${CR}" |
| else |
| adb wait-for-recovery |
| ret=${?} |
| fi |
| USB_DEVICE=`usb_devnum` |
| if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then |
| local active_slot=`get_active_slot` |
| if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then |
| echo "${ORANGE}[ WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" |
| fi >&2 |
| fi |
| return ${ret} |
| } |
| |
| [ "any_wait [timeout] |
| |
| Returns: waits until a device has returned or optional timeout" ] |
| any_wait() { |
| ( |
| adb_wait ${1} & |
| adb_pid=${!} |
| fastboot_wait ${1} & |
| fastboot_pid=${!} |
| recovery_wait ${1} & |
| recovery_pid=${!} |
| wait -n |
| kill "${adb_pid}" "${fastboot_pid}" "${recovery_pid}" |
| ) >/dev/null 2>/dev/null |
| inFastboot || inAdb || inRecovery |
| } |
| |
| ## |
| ## RUNTIME |
| ## |
| |
| filter= |
| output=- |
| input= |
| display=false |
| force=false |
| while [ ${#} -gt 0 ]; do |
| case ${1} in |
| -f=* | --filter=*) |
| filter="${1#-f=}" |
| filter="${filter#--filter=}" |
| ;; |
| -f | --filter) |
| if [ ${#} = 1 -o -z "${2}" ]; then |
| filter=- |
| else |
| shift |
| filter="${1}" |
| fi |
| ;; |
| -F | --force) |
| force=true |
| ;; |
| -h | -\? | --help) |
| echo "${USAGE}" |
| exit 0 |
| ;; |
| -o=* | --output=*) |
| output="${1#-o=}" |
| output="${output#--output=}" |
| ;; |
| -o | --output) |
| if [ ${#} = 1 -o -z "${2}" ]; then |
| # empty output results in no dmesg or probed collection |
| output= |
| else |
| shift |
| output="${1}" |
| fi |
| ;; |
| -d=* | --diff=*) |
| input="${1#-d=}" |
| input="${input#--diff=}" |
| ;; |
| -d | --diff) |
| shift |
| input="${1}" |
| ;; |
| -D | --wait-for-display) |
| display=true |
| ;; |
| -s=* | --serial=*) |
| ANDROID_SERIAL="${1#-s=}" |
| export ANDROID_SERIAL="${ANDROID_SERIAL#--serial=}" |
| ;; |
| -s | --serial) |
| shift |
| export ANDROID_SERIAL="${1}" |
| ;; |
| *) |
| echo "${RED}[ ERROR ]${NORMAL} unknown parm ${1}" >&2 |
| echo "${USAGE}" >&2 |
| exit 1 |
| ;; |
| esac |
| shift |
| done |
| |
| if [ -n "${input}" -a -z "${output#-}" ]; then |
| echo "${RED}[ ERROR ]${NORMAL} must specify an -o <output> along with the -d ${input}" >&2 |
| echo "${USAGE}" >&2 |
| exit 1 |
| fi |
| |
| USB_SERIAL= |
| [ -z "${ANDROID_SERIAL}" ] || USB_SERIAL=`find /sys/devices -name serial | |
| grep usb | |
| xargs grep -l ${ANDROID_SERIAL}` |
| USB_ADDRESS= |
| if [ -n "${USB_SERIAL}" ]; then |
| USB_ADDRESS=${USB_SERIAL%/serial} |
| USB_ADDRESS=usb${USB_ADDRESS##*/} |
| fi |
| |
| [ "USAGE: input= BLUE= output= NORMAL= perform_diff < ${output} |
| |
| Reports the differences between stdin and \${input}" ] |
| perform_diff() { |
| diff -U1 "${input}" - | |
| # Squash noise, replacing long stretches of changes with trailing ... |
| sed '/^@@ -1,[0-9]\{4,\} [+]0,0 @@$/ q |
| /^@@ -0,0 [+]1,[0-9]\{4,\} @@$/ q |
| /^-\/sys\/module\/[^\/]*\/sections\/[.]bss$/ { |
| N |
| /^\(-\/sys\/module\/[^\/]*\/sections\/[.]\)bss\n\1data$/ { |
| : loop |
| N |
| /^-\(\/sys\/module\/[^\/]*\/sections\/[.]\)bss\n-\1data.*\n[+]\1bss[.][^\n]*$/ b loop |
| s/^-\(\/sys\/module\/[^\/]*\/sections\/[.]\)bss\n-\1data\(.*\n[+]\1bss[.][^\n]*\)\(\n\)\([^\n]*\)$/-\1bss\2\3-\1data\3\4/ |
| } |
| }' | |
| sed '/^[-+ ]\/sys\/module\/[^\/]*$/ { |
| : loop1 |
| N |
| /^ \([^\n]*\)\n[+]\1\/\(coresize\|parameters\)$/ b loop2 |
| /^\([-+][^\n]*\)\n\1\/\(coresize\|parameters\)$/ { |
| : loop2 |
| N |
| /^\([-+][^\n]*\)\n.*\n\1\/uevent$/ b skip1 |
| /^ \([^\n]*\)\n.*\n[+]\1\/uevent$/ b skip2 |
| /^ \([^\n]*\)\n.*\n[+]\1\/[^\n]*$/ b loop2 |
| /^\([-+][^\n]*\)\n.*\n\1\/[^\n]*$/ b loop2 |
| h |
| s/^\([-+][^\n]*\)\n.*\n\1\/[^\n]*\n[^\n]*$/\1\/.../ |
| s/^ \([^\n]*\)\(\n\).*\n[+]\1\/[^\n]*\n[^\n]*$/ \1\2+\1\/.../ |
| p |
| g |
| s/^.*\n\([^\n]*\)$/\1/ |
| /^[-+ ]\/sys\/module\/[^\/]*$/ b loop1 |
| b exit |
| : skip1 |
| s/^\([^\n]*\)\n.*\n\1\/uevent$/\1\/.../ |
| b exit |
| : skip2 |
| s/^ \([^\n]*\)\(\n\).*\n[+]\1\/uevent$/\1\2\1\/.../ |
| : exit |
| } |
| } |
| /^[-+]\/sys\/module\/[^\/]*\/refcnt$/ { |
| : loop3 |
| N |
| /^\([-+][^\n]*\/\)refcnt.*\n\1[^\n]*$/ b loop3 |
| h |
| s/^\([-+][^\n]*\/\)\(refcnt\n\).*\n\1[^\n]*\n[^\n]*$/\1\2\1.../ |
| p |
| g |
| s/^.*\n\([^\n]*\)$/\1/ |
| /^[-+ ]\/sys\/module\/[^\/]*$/ b loop1 |
| } |
| /^-\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)$/ { |
| : loop4 |
| N |
| /^-\(\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)\).*\n[+]\1[.][^\n]*$/ b loop4 |
| h |
| s/^-\(\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)\)\n.*\(\n\)[+]\1[.][^\n]*\n[^\n]*$/-\1\3+\1.../ |
| s/^-\(\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)\)\n[^\n]*[^.][^.]$/-\1/ |
| s/^-\(\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)\)\(\n[+]\1[.][^\n]*\)\n[^\n]*[^.][^.]$/-\1\3/ |
| p |
| g |
| s/^.*\n\([^\n]*\)$/\1/ |
| /^-\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)$/ b loop4 |
| /^[-+ ]\/sys\/module\/[^\/]*$/ b loop1 |
| } |
| /^ \/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)[.]/ { |
| : loop5 |
| N |
| /^ \(\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)\)[.][^\n].*\n[+]\1[.][^\n]*$/ b loop5 |
| h |
| s/^ \(\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)\)\([.][^\n]*\n\).*\n[+]\1[.][^\n]*\n[^\n]*$/ \1\3+\1.../ |
| s/^\( \/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)[.][^\n]*\)\n[^\n]*[^.][^.]$/\1/ |
| p |
| g |
| s/^.*\n\([^\n]*\)$/\1/ |
| /^ \/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)[.]/ b loop5 |
| /^-\/sys\/module\/[^\/]*\/sections\/[.]\(bss\|data\|rodata\|text\)$/ b loop4 |
| /^[-+ ]\/sys\/module\/[^\/]*$/ b loop1 |
| }' | |
| grep '[-+ ]' || |
| echo "${BLUE}[ INFO ]${NORMAL} no differences in /dev/ and /sys/ since last device snapshot" >&2 |
| if [ -s "${output}.probed" -a -s "${input}.probed" ]; then |
| diff -U1 "${input}.probed" "${output}.probed" | |
| grep '[-+ ]' || |
| echo "${BLUE}[ INFO ]${NORMAL} no differences in probed devices and drivers" >&2 |
| fi |
| if [ -s "${output}.dmesg" -a -s "${input}.dmesg" ]; then |
| TMP=`mktemp -d` |
| mknod ${TMP}/input p |
| sed -n 's@^.*init: Loaded kernel module /lib/modules/@@p' ${input}.dmesg > ${TMP}/input & |
| sed -n 's@^.*init: Loaded kernel module /lib/modules/@@p' ${output}.dmesg | |
| diff -U1 ${TMP}/input - | |
| grep '[-+ ]' || |
| echo "${BLUE}[ INFO ]${NORMAL} no differences in module load order" >&2 |
| wait |
| rm -rf ${TMP} |
| fi |
| if [ -s "${output}.config" -a -s "${input}.config" ]; then |
| diff -U1 "${input}.config" "${output}.config" | |
| grep '[-+ ]' || |
| echo "${BLUE}[ INFO ]${NORMAL} no differences in config" >&2 |
| fi |
| if [ -s "${output}.getprop" -a -s "${input}.getprop" ]; then |
| TMP=`mktemp -d` |
| sed -n 's/[[]ro[.]boottime[.]\([^]]*\)[]]: [[]\([0-9]*\)[]]$/\1 \2/p' "${input}.getprop" >${TMP}/old.getprop |
| sed -n 's/[[]ro[.]boottime[.]\([^]]*\)[]]: [[]\([0-9]*\)[]]$/\2 \1/p' "${output}.getprop" | |
| sort -un | |
| while read monotonic action; do |
| [ -n "${action}" ] || continue |
| [ -n "${monotonic}" ] || continue |
| old=`sed -n "s/^${action} //p" ${TMP}/old.getprop` |
| [ -n "${old}" ] || continue |
| old="$((${monotonic} - ${old}))" |
| [ -n "${old}" -a 0 != "${old}" ] || continue |
| sign=+ |
| if [ -z "${old##-*}" ]; then |
| sign=- |
| old=${old#-} |
| fi |
| printf "${action}\t${sign}%u.%09us\n" $((${old} / 1000000000)) $((${old} % 1000000000)) |
| done | |
| grep '[0-9][.][0-9]' || |
| echo "${BLUE}[ INFO ]${NORMAL} no differences in boottime" >&2 |
| rm -rf ${TMP} |
| fi |
| } |
| |
| if [ -n "${output#-}" -a -s "${output}" ]; then |
| if ! ${force}; then |
| if [ -n "${input}" ]; then |
| perform_diff <${output} |
| exit 0 |
| fi |
| echo "${RED}[ ERROR ]${NORMAL} will not overwrite existing content" >&2 |
| exit 1 |
| fi |
| fi |
| |
| if [ -z "${filter}" ]; then |
| if inFastboot; then |
| echo "${RED}[ ERROR ]${NORMAL} in fastboot mode" >&2 |
| exit 1 |
| fi |
| if inRecovery; then |
| echo "${RED}[ ERROR ]${NORMAL} in recovery mode" >&2 |
| exit 1 |
| fi |
| if ! inAdb; then |
| any_wait 2m |
| if ! inAdb; then |
| if [ -n "${ANDROID_SERIAL}" ]; then |
| echo "${RED}[ ERROR ]${NORMAL} not in adb mode" >&2 |
| exit 1 |
| fi |
| COUNT=`adb devices </dev/null | |
| grep -v -e 'List of devices attached' -e '^$' | |
| wc -l` |
| echo "${RED}[ ERROR ]${NORMAL} ${COUNT} devices attached" >&2 |
| exit 1 |
| fi |
| fi |
| counter=0 |
| while ${display}; do |
| if inFastboot; then |
| fastboot reboot |
| elif inAdb; then |
| if [ "1" = "`get_property sys.boot_completed`" ]; then |
| break |
| fi |
| fi |
| counter=$((${counter} + 1)) |
| if [ ${counter} -gt 120 ]; then |
| break |
| fi |
| sleep 1 |
| done |
| fi |
| |
| if [ -n "${filter}" ]; then |
| cat ${filter} |
| else |
| adb_su find /dev /sys </dev/null 2>/dev/null | |
| if [ -n "${output}" -a X"${output}" != X"-" ]; then |
| # Generate ${output}.probed: |
| # |
| # Report all the instantiated devices and which driver is responsible. |
| # If drivers do not have any instantiated devices, report them at end. |
| # Drivers are of a form driver:<subsystem>:<name>, if <subsystem> is |
| # empty, it is short hand for platform. |
| # |
| DRIVERS= |
| FOUND= |
| ( |
| tee /proc/self/fd/99 | |
| sed -n \ |
| -e 's@/sys/devices/platform/.*/driver$@&@p' \ |
| -e 's@/sys/bus/\([^/]*\)/drivers/\([^/]*\)$@driver:\1:\2@p' | |
| sort -u |
| echo DONE |
| ) | |
| while read driver; do |
| [ -n "${driver}" ] || continue |
| case ${driver} in |
| DONE) |
| [ -n "${DRIVERS}" ] || break |
| if [ -z "${FOUND}" ]; then |
| echo "${DRIVERS}" |
| else |
| echo "${DRIVERS}" | |
| grep -ve "${FOUND}\)\$" || |
| true |
| fi | |
| sed 's/driver:platform:/driver::/' |
| break |
| ;; |
| driver:*) |
| [ -z "${DRIVERS}" ] || DRIVERS="${DRIVERS} |
| " |
| DRIVERS="${DRIVERS}${driver}" |
| ;; |
| *) |
| INSTANCE="${driver#/sys/devices/platform/}" |
| INSTANCE="${INSTANCE%/driver}" |
| DRIVER="`adb_su ls -l ${driver} </dev/null 2>/dev/null | |
| sed -n 's@.* -> .*/bus/\([^/]*\)/drivers/\(.*\)@driver:\1:\2@p'`" |
| if [ -z "${DRIVER}" ]; then |
| echo "${INSTANCE}" |
| else |
| if [ -z "${FOUND}" ]; then |
| FOUND="^\(${DRIVER}" |
| else |
| FOUND="${FOUND}\|${DRIVER}" |
| fi |
| DRIVER="${DRIVER#driver:}" |
| echo "${INSTANCE} -> driver:${DRIVER#platform}" |
| fi |
| ;; |
| esac |
| done >"${output}.probed" |
| [ -s "${output}.probed" ] || rm -f "${output}.probed" |
| # Generate ${output}.dmesg |
| adb_su dmesg </dev/null 2>/dev/null >"${output}.dmesg" |
| [ -s "${output}.dmesg" ] || rm -f "${output}.dmesg" |
| # Generate ${output}.config if kernel provides it. |
| adb_su cat /proc/config.gz </dev/null 2>/dev/null | |
| gunzip >"${output}.config" |
| [ -s "${output}.config" ] || rm -f "${output}.config" |
| # Generate ${output}.getprop |
| adb $QD shell su root getprop </dev/null 2>/dev/null | |
| sort -u >"${output}.getprop" |
| [ -s "${output}.getprop" ] || rm -f "${output}.getprop" |
| else |
| cat - >&99 |
| fi 99>&1 |
| fi | |
| grep -v '^\(/dev/ashmem\|/dev/block/mapper/by-uuid/\|/dev/fscklogs/log\)' | |
| grep -v '^\(/dev/socket/location/\(socket_hal\|cld80211\)\|/sys/class/hwmon/\)' | |
| grep -v '^/dev/socket/netmgr/netmgr_connect_socket$' | |
| grep -v '^/dev/socket/qdma/qdma-\(file\|campmgr\)-s$' | |
| grep -v '^/dev/socket/qmux_radio/' | |
| grep -v '^/dev/socket/vendor_wpa_wlan' | |
| grep -v '^/dev/socket/wifihal/wifihal_ctrlsock' | |
| grep -v '^/sys/dev/char/[0-9]*:[0-9]*$' | |
| grep -v '^/sys/devices/virtual/thermal/tz-by-name/wsatz[.][0-9]*$' | |
| grep -v '^/sys/kernel/debug/tracing/instances/wifi' | |
| grep -v '^/sys/kernel/debug/\(wlan\|WMI\|p2p\|msm-bus-dbg/client-data/npu_bwmon_cdsp\)' | |
| grep -v '^/sys/class/net/\(wlan\|p2p\)' | |
| grep -v '^/sys/class/ieee80211/phy' | |
| grep -v '^/sys/devices/platform/soc/[0-9a-f]*.qcom,icnss/\(net\|firmware\|ieee80211\)' | |
| grep -v '^/sys/devices/platform/soc/[0-9a-f]*.*@[0-9][0-9]*-cam_\(vana\|vdig\|vio\|clk\)$' | |
| grep -v '^/sys/kernel/wlan/' | |
| grep -v '^/sys/kernel/slab/\(f2fs_fsync_inode_entry\|zs\|:[0-9a-f]\{,7\}\)' | |
| grep -v '^/sys/devices/system/cpu/cpufreq/policy[0-9]*/schedutil' | |
| grep -v '/__trace_printk_fmt$' | |
| sed "s@\(/regulator[.]\)[0-9][0-9]*\$@\1${NUM}@ |
| s@\(/regulator[.]\)[0-9][0-9]*/@\1${NUM}/@g |
| s@\(/vppservice_\)[0-9][0-9]*\$@\1${NUM}@ |
| s@\(/msi_irqs/\)[0-9][0-9]*\$@\1${NUM}@ |
| s@\(/sys/class/rfkill/rfkill\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/class\|/sys/devices/platform/soc/[0-9a-f]*[.]qcom,gpi-dma\)\(/dma/dma\)[0-9]*\(chan[0-9]*\(\|/.*\)\)\$@\1\2${NUM}\3@ |
| s@\(/i2c-\)\([0-9]\)\(/[^/]*/i2c-\)\2\(\|/.*\)\$@\1${NUM}\3${NUM}\4@ |
| s@\(/i2c-\)[0-9]\(\|/[^/]*\)\$@\1${NUM}\2@ |
| s@-\([0-9]\)/\1\(-[0-9][0-9][0-9][0-9]/\)@-${NUM}/${NUM}\2@g |
| s@/[0-9]\(-[0-9][0-9][0-9][0-9]\(\|-vdd\|-vdd/.*\|-avdd\|-avdd/.*\|-vio\|-vio/.*\|/.*\)\)\$@${NUM}\1@ |
| s@\(/sys/devices/platform/soc/[0-9a-z]*[.]qcom,[^/]*/subsys\)[0-9][0-9]*@\1${NUM}@ |
| s@\(rpmsg_chrdev[.]0[.]0/rpmsg/rpmsg_ctrl\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/devices/virtual/kgsl/kgsl/pagetables/\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/devices/virtual/kgsl/kgsl/proc/\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/devices/virtual/thermal/thermal_zone\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/devices/virtual/net/\)\(r_\|\)\(rmnet_data\)[0-9][0-9]*\(/queues/tx-\)[0-9][0-9]*@\1\3${NUM}\4${NUM}@ |
| s@\(/sys/devices/platform/soc/soc:qcom,msm-audio-apr/soc:qcom,msm-audio-apr:qcom,q6core-audio/soc:qcom,msm-audio-apr:qcom,q6core-audio:lpi_pinctrl[@][0-9a-f]*/gpiochip\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/kernel/debug/adsprpc/\(adsp\|cdsp\|ssc\)rpcd_\)[0-9][0-9]*\$@\1${NUM}@ |
| s@\(/sys/kernel/debug/binder/proc/\)[0-9][0-9]*\$@\1${NUM}@ |
| s@\(/sys/kernel/debug/kgsl/proc/\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/kernel/debug/kgsl/kgsl-[0-9a-f][0-9a-f]*/ctx/\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/sys/module/[^/]*/sections/.*[.]llvm[.]\)[0-9][0-9]*\$@\1${NUM}@ |
| s@\(/sys/kernel/debug/msm_cvp/core0/inst_\)[0-9a-f][0-9a-f]*@\1${NUM}@ |
| s@\(/sys/kernel/iommu_groups/\)[0-9][0-9]*@\1${NUM}@ |
| s@\(/devices/soc:qcom,msm_fastrpc:qcom,msm_fastrpc_compute_cb\)[0-9][0-9]*@\1${NUM}@ |
| s@/mmc[0-9][0-9]*\($\|/\|:\)@/mmc${NUM}\1@ |
| s@\(/sys/kernel/irq/\)[0-9][0-9]*@\1${NUM}@" | |
| if [ -n "${output}" -a X"${output}" != X"-" ]; then |
| sort -u | |
| if [ -n "${input}" ]; then |
| tee "${output}" | perform_diff |
| else |
| cat - >"${output}" |
| fi |
| [ -s "${output}" ] || rm -f "${output}" |
| else |
| TMP=`mktemp -d` |
| if [ X"${output}" = X"-" ]; then |
| echo "------------------------> cut dump < ------------------------" |
| sort -u | |
| tee /proc/self/fd/99 | |
| sed -n 's@/sys/devices/platform/\(.*\)/driver$@\1@p' >${TMP}/probed |
| else |
| sort -u >&99 |
| fi 99>&1 |
| if [ -s "${TMP}/probed" ]; then |
| echo "-----------------------> cut probed <------------------------" |
| cat ${TMP}/probed |
| fi |
| rm -rf ${TMP} |
| fi |
| if [ -z "${filter}" -a X"${output}" = X"-" ]; then |
| echo "------------------------> cut dmesg <------------------------" |
| adb_su dmesg </dev/null 2>/dev/null |
| echo "-----------------------> cut .config <-----------------------" |
| adb_su cat /proc/config.gz </dev/null 2>/dev/null | gunzip |
| fi |