| #! /bin/sh |
| # SPDX-License-Identifier: GPL-2.0 |
| # Copyright (c) 2022, Google LLC. All rights reserved. |
| # Author: Isaac J. Manjarres <[email protected]> |
| |
| DIR="$(dirname $(readlink -f $0))" |
| DEV_NEEDS_HOST_PATH="${DIR}/dev-needs.sh" |
| |
| DEV_TMP_DIR="/data/local/tmp" |
| DEV_NEEDS_DEV_PATH="${DEV_TMP_DIR}/$(basename ${DEV_NEEDS_HOST_PATH})" |
| |
| REVERSE_DRIVER_DEP_LIST=0 |
| WANT_MOD_LOAD_ORDER=0 |
| |
| TSORTED_DEV_LIST= |
| OUTPUT_LIST= |
| |
| prepare_device() { |
| adb wait-for-device root >/dev/null |
| if [ $? -ne 0 ]; then |
| echo "Failed to root device" |
| return 1 |
| fi |
| |
| adb push "${DEV_NEEDS_HOST_PATH}" "${DEV_TMP_DIR}/" >/dev/null |
| if [ $? -ne 0 ]; then |
| echo "Failed to push the dev-needs.sh script to the device" |
| return 1 |
| fi |
| |
| return 0 |
| } |
| |
| cleanup_device() { |
| adb shell "rm ${DEV_NEEDS_DEV_PATH}" |
| } |
| |
| remove_duplicate_list_entries () { |
| local list_entries="${1}" |
| local tmp_list_file=$(mktemp) |
| |
| echo -n "${list_entries}" > "${tmp_list_file}" |
| |
| # Remove duplicates--except for the first occurrence--while keeping |
| # the list in the same order |
| OUTPUT_LIST=$(cat -n "${tmp_list_file}" | sort -uk2 | sort -n | cut -f2-) |
| rm "${tmp_list_file}" |
| } |
| |
| get_dev_compat() { |
| local dev=$1 |
| local compat_str=$(adb shell "cat '$dev'/of_node/compatible 2>/dev/null" | tr -d '\0') |
| |
| if [ -n "${compat_str}" ]; then |
| OUTPUT_LIST+="${compat_str}"$'\n' |
| fi |
| } |
| |
| devs_to_compat_list() { |
| local dev_list="${1}" |
| |
| for dev in ${dev_list[@]}; do |
| get_dev_compat "${dev}" |
| done |
| } |
| |
| get_dev_module_name() { |
| local dev=$1 |
| local module_path=$(adb shell "realpath '$dev'/driver/module 2>/dev/null") |
| |
| if [ -n "${module_path}" ]; then |
| OUTPUT_LIST+=$(basename "${module_path}")$'\n' |
| fi |
| } |
| |
| devs_to_module_list() { |
| local dev_list="${1}" |
| |
| for dev in ${dev_list[@]}; do |
| get_dev_module_name "${dev}" |
| done |
| } |
| |
| get_tsorted_dev_list() { |
| local tsort_edges |
| |
| tsort_edges=$(adb shell ''${DEV_NEEDS_DEV_PATH}' -t\ |
| $(find /sys/devices -name driver | sed -e "s/\/driver//")') |
| TSORTED_DEV_LIST=$(echo "${tsort_edges}" | tsort | sed -e "s/\"//g") |
| } |
| |
| while getopts "s:rl" f; do |
| case "$f" in |
| s) export ANDROID_SERIAL="${OPTARG}" ;; |
| r) REVERSE_DRIVER_DEP_LIST=1 ;; |
| l) WANT_MOD_LOAD_ORDER=1 ;; |
| esac |
| done |
| |
| if [ $REVERSE_DRIVER_DEP_LIST = 1 ] && [ $WANT_MOD_LOAD_ORDER = 1 ]; then |
| exit 1 |
| elif [ ! -f "${DEV_NEEDS_HOST_PATH}" ]; then |
| echo "Kernel does not contain the required dev-needs.sh script" |
| exit 1 |
| fi |
| |
| if ! prepare_device; then |
| exit 1 |
| fi |
| |
| get_tsorted_dev_list |
| |
| if [ $WANT_MOD_LOAD_ORDER = 1 ]; then |
| devs_to_module_list "${TSORTED_DEV_LIST}" |
| else |
| devs_to_compat_list "${TSORTED_DEV_LIST}" |
| fi |
| |
| remove_duplicate_list_entries "${OUTPUT_LIST}" |
| |
| if [ $REVERSE_DRIVER_DEP_LIST = 1 ]; then |
| echo "${OUTPUT_LIST}" | tac |
| else |
| echo "${OUTPUT_LIST}" |
| fi |
| |
| cleanup_device |