17a1bd398SMichal Berger#!/usr/bin/env bash 27a1bd398SMichal Berger# SPDX-License-Identifier: BSD-3-Clause 37a1bd398SMichal Berger# Copyright (C) 2023 Intel Corporation 47a1bd398SMichal Berger# All rights reserved. 57a1bd398SMichal Berger# 67a1bd398SMichal Bergerset +e 77a1bd398SMichal Berger 87a1bd398SMichal Bergeryn() { 97a1bd398SMichal Berger local -A yn=() 107a1bd398SMichal Berger local _yn 117a1bd398SMichal Berger 127a1bd398SMichal Berger yn["y"]=0 yn["n"]=1 137a1bd398SMichal Berger 147a1bd398SMichal Berger while read -rp "$* (y|N)> " _yn || true; do 157a1bd398SMichal Berger _yn=${_yn::1} _yn=${_yn,,} _yn=${_yn:-n} 167a1bd398SMichal Berger [[ -n ${yn["$_yn"]} ]] && return "${yn["$_yn"]}" 177a1bd398SMichal Berger done 187a1bd398SMichal Berger} 197a1bd398SMichal Berger 207a1bd398SMichal Bergerelevate() { 217a1bd398SMichal Berger ((UID != 0)) || return 0 227a1bd398SMichal Berger 237a1bd398SMichal Berger if yn "You ($UID) need to be root to commit any changes. Elevate privileges?"; then 2444fef7d2SMichal Berger exec sudo -E "$rootdir/scripts/setup.sh" interactive "$@" 257a1bd398SMichal Berger fi 267a1bd398SMichal Berger} 277a1bd398SMichal Berger 287a1bd398SMichal Bergerstdin() { 297a1bd398SMichal Berger [[ ! -t 0 ]] || return 0 307a1bd398SMichal Berger 317a1bd398SMichal Berger echo "Requested interactive mode but stdin is not attached to a terminal, bailing" >&2 327a1bd398SMichal Berger return 1 337a1bd398SMichal Berger} 347a1bd398SMichal Berger 357a1bd398SMichal Bergermain_menu() { 3644fef7d2SMichal Berger local type=all answer quick_mode=$1 377a1bd398SMichal Berger 387a1bd398SMichal Berger stdin || return 1 3944fef7d2SMichal Berger elevate "$quick_mode" 4044fef7d2SMichal Berger 4144fef7d2SMichal Berger case "${quick_mode,,}" in 4244fef7d2SMichal Berger config | reset) 4344fef7d2SMichal Berger editor odevices quick && mode=$quick_mode 4444fef7d2SMichal Berger return 4544fef7d2SMichal Berger ;; 4644fef7d2SMichal Berger esac 477a1bd398SMichal Berger 487a1bd398SMichal Berger while ((1)); do 497a1bd398SMichal Berger cat <<- MENU 507a1bd398SMichal Berger 517a1bd398SMichal Berger 1) List PCI Devices [Currently Listing: "$type"] 527a1bd398SMichal Berger 2) Change Devices To List 537a1bd398SMichal Berger 3) Mark Device As Blocked (${PCI_BLOCKED:-none}) 547a1bd398SMichal Berger 4) Mark Device As Allowed (${PCI_ALLOWED:-none}) 557a1bd398SMichal Berger 5) Override Device In-Use Status 567a1bd398SMichal Berger $([[ $os == Linux ]] && echo "6) Bind Device") 577a1bd398SMichal Berger 587a1bd398SMichal Berger c) configure 597a1bd398SMichal Berger s) status 607a1bd398SMichal Berger r) reset 617a1bd398SMichal Berger $([[ $os == Linux ]] && echo "hp) hugepages") 627a1bd398SMichal Berger 637a1bd398SMichal Berger Q) Quit 647a1bd398SMichal Berger U) Update Devices View 657a1bd398SMichal Berger 667a1bd398SMichal Berger MENU 677a1bd398SMichal Berger 687a1bd398SMichal Berger read -rp "> " answer || answer=q 697a1bd398SMichal Berger 707a1bd398SMichal Berger case "${answer,,}" in 717a1bd398SMichal Berger 1) pdevices ;; 727a1bd398SMichal Berger 2) ctype && pdevices ;; 737a1bd398SMichal Berger 3) fdevices 0 ;; 747a1bd398SMichal Berger 4) fdevices 1 ;; 757a1bd398SMichal Berger 5) odevices ;; 76daf647bcSMichal Berger 5e) editor odevices ;; 77c97b31f8SMichal Berger 6) bdevices ;;& 787a1bd398SMichal Berger q) yn "Are you sure you want to quit?" && return 1 ;; 797a1bd398SMichal Berger c | commit | config) 807a1bd398SMichal Berger yn "Are you sure you want jump to config mode?" || continue 817a1bd398SMichal Berger mode=config 827a1bd398SMichal Berger return 837a1bd398SMichal Berger ;; 84c97b31f8SMichal Berger hp) hugepages ;; 857a1bd398SMichal Berger s | status) status ;; 867a1bd398SMichal Berger r | reset) 877a1bd398SMichal Berger yn "Are you sure you want jump to reset mode?" || continue 887a1bd398SMichal Berger mode=reset 897a1bd398SMichal Berger return 907a1bd398SMichal Berger ;; 91c97b31f8SMichal Berger 6 | u | update) update_status ;; 927a1bd398SMichal Berger esac 937a1bd398SMichal Berger done 947a1bd398SMichal Berger} 957a1bd398SMichal Berger 967a1bd398SMichal Bergergdevices() { 977a1bd398SMichal Berger if [[ $type == all ]]; then 987a1bd398SMichal Berger local -gn dev_ref=all_devices_d 997a1bd398SMichal Berger else 1007a1bd398SMichal Berger local -gn dev_ref=${type}_d 1017a1bd398SMichal Berger fi 1027a1bd398SMichal Berger} 1037a1bd398SMichal Berger 1047a1bd398SMichal Bergerpdevices() { 1057a1bd398SMichal Berger gdevices 1067a1bd398SMichal Berger 107daf647bcSMichal Berger local set_marker=$1 1087a1bd398SMichal Berger local use_map=() 109daf647bcSMichal Berger local -A markers=() 110daf647bcSMichal Berger 1117a1bd398SMichal Berger use_map[0]="not used" use_map[1]="used" 112daf647bcSMichal Berger markers["not used"]=pick markers["used"]=skip 1137a1bd398SMichal Berger 1147a1bd398SMichal Berger if ((${#dev_ref[@]} == 0)); then 1157a1bd398SMichal Berger echo "No devices found" 1167a1bd398SMichal Berger else 1177a1bd398SMichal Berger for dev in "${!dev_ref[@]}"; do 1184f8177b5SMichal Berger printf '%s- %s [%s, %s] (%s@%s:%s)%s\n' \ 119daf647bcSMichal Berger "${set_marker:+${markers["${use_map[all_devices_d["$dev"]]}"]} }" \ 1204f8177b5SMichal Berger "$dev" "${use_map[all_devices_d["$dev"]]}" "${pci_bus_driver["$dev"]:-none}" \ 121f1068fefSMichal Berger "${all_devices_type_d["$dev"]}" \ 122f1068fefSMichal Berger "${pci_ids_vendor["$dev"]}" \ 1234f8177b5SMichal Berger "${pci_ids_device["$dev"]}" \ 1244f8177b5SMichal Berger "${nvme_vmd_d["$dev"]:+"@(VMD -> ${nvme_vmd_d["$dev"]})"}" 1257a1bd398SMichal Berger done 1267a1bd398SMichal Berger fi 1277a1bd398SMichal Berger} 1287a1bd398SMichal Berger 1297a1bd398SMichal Bergerctype() { 1307a1bd398SMichal Berger local type_to_set 1317a1bd398SMichal Berger local -n types_ref=types_d 1327a1bd398SMichal Berger 1337a1bd398SMichal Berger while read -rp "(${!types_ref[*]} all)> " type_to_set; do 1347a1bd398SMichal Berger type_to_set=${type_to_set,,} 1357a1bd398SMichal Berger if [[ -z $type_to_set ]]; then 1367a1bd398SMichal Berger return 1377a1bd398SMichal Berger elif [[ -n ${types_ref["$type_to_set"]} || $type_to_set == all ]]; then 1387a1bd398SMichal Berger type=$type_to_set 1397a1bd398SMichal Berger return 1407a1bd398SMichal Berger fi 1417a1bd398SMichal Berger done 1427a1bd398SMichal Berger} 1437a1bd398SMichal Berger 1447a1bd398SMichal Bergerfdevices() { 1457a1bd398SMichal Berger local action=${1:-0} bdf 1467a1bd398SMichal Berger local am=() 1477a1bd398SMichal Berger local -gA action_0 action_1 1487a1bd398SMichal Berger 1497a1bd398SMichal Berger am[0]=PCI_BLOCKED am[1]=PCI_ALLOWED 1507a1bd398SMichal Berger 1517a1bd398SMichal Berger gdevices 1527a1bd398SMichal Berger local -n action_ref=action_${action} 1537a1bd398SMichal Berger local -n action_ref_rev=action_$((!action)) 1547a1bd398SMichal Berger 1557a1bd398SMichal Berger while read -rp "(${!am[action]:-BDF})> " bdf; do 1567a1bd398SMichal Berger bdf=${bdf,,} 1577a1bd398SMichal Berger if [[ -z $bdf ]]; then 1587a1bd398SMichal Berger return 1597a1bd398SMichal Berger elif [[ -n ${dev_ref["$bdf"]} ]]; then 1607a1bd398SMichal Berger if [[ -n ${action_ref["$bdf"]} ]]; then 1617a1bd398SMichal Berger unset -v "action_ref[$bdf]" 1627a1bd398SMichal Berger else 1637a1bd398SMichal Berger action_ref["$bdf"]=1 1647a1bd398SMichal Berger unset -v "action_ref_rev[$bdf]" 1657a1bd398SMichal Berger fi 1667a1bd398SMichal Berger eval "${am[action]}='${!action_ref[*]}'" 1677a1bd398SMichal Berger eval "${am[!action]}='${!action_ref_rev[*]}'" 1687a1bd398SMichal Berger elif [[ -z ${dev_ref["$bdf"]} ]]; then 1697a1bd398SMichal Berger unset -v "action_ref[$bdf]" 1707a1bd398SMichal Berger eval "${am[action]}='${!action_ref[*]}'" 1717a1bd398SMichal Berger fi 1727a1bd398SMichal Berger done 1737a1bd398SMichal Berger} 1747a1bd398SMichal Berger 175daf647bcSMichal Bergereditor() { 17644fef7d2SMichal Berger local devs_list=() devs_picked=() devs_skipped=() 177daf647bcSMichal Berger local editor=${VISUAL:-${EDITOR:-vim}} 178daf647bcSMichal Berger local tmp_file 179daf647bcSMichal Berger 180daf647bcSMichal Berger type -P "$editor" > /dev/null || return 181daf647bcSMichal Berger 182daf647bcSMichal Berger mapfile -t devs_list < <(pdevices markers) 183daf647bcSMichal Berger 184daf647bcSMichal Berger tmp_file=$(mktemp -u) 185daf647bcSMichal Berger cat <<- ODEVICES > "$tmp_file" || return 186daf647bcSMichal Berger # Listing '$type' devices 187daf647bcSMichal Berger # Devices marked as "used" (i.e. contains any data) will be skipped by default 188daf647bcSMichal Berger # Devices marked as "not used" (i.e. does not contain data) will be picked by default 189daf647bcSMichal Berger 190daf647bcSMichal Berger $(printf '%s\n' "${devs_list[@]}") 191daf647bcSMichal Berger 192daf647bcSMichal Berger # p, pick devices 193daf647bcSMichal Berger # s, skip devices 194daf647bcSMichal Berger 195daf647bcSMichal Berger $([[ $editor == vi?(m) ]] && echo "# :cq[!] to not save any changes") 196daf647bcSMichal Berger ODEVICES 197daf647bcSMichal Berger 198daf647bcSMichal Berger "$editor" "$tmp_file" || return 199daf647bcSMichal Berger [[ -s $tmp_file ]] || return 200daf647bcSMichal Berger 201daf647bcSMichal Berger local action dev _type 202daf647bcSMichal Berger while read -r action _ dev _type; do 203daf647bcSMichal Berger case "${action,,}" in 204daf647bcSMichal Berger s | skip) 205daf647bcSMichal Berger [[ $_type != *"not used"* ]] && continue 20644fef7d2SMichal Berger devs_skipped+=("$dev") 207daf647bcSMichal Berger ;; 208daf647bcSMichal Berger p | pick) 209daf647bcSMichal Berger [[ $_type == *"not used"* ]] && continue 21044fef7d2SMichal Berger devs_picked+=("$dev") 211daf647bcSMichal Berger ;; 212daf647bcSMichal Berger esac 213daf647bcSMichal Berger done < "$tmp_file" 214daf647bcSMichal Berger rm "$tmp_file" 215daf647bcSMichal Berger 21644fef7d2SMichal Berger if [[ $2 == quick ]] && ((${#devs_picked[@]} > 0)); then 21744fef7d2SMichal Berger if ! yn "Detected data on some of the devices (${devs_picked[*]}). Continue?"; then 21844fef7d2SMichal Berger return 1 21944fef7d2SMichal Berger fi 22044fef7d2SMichal Berger fi 22144fef7d2SMichal Berger 22244fef7d2SMichal Berger "$1" < <(printf '%s\n' "${devs_skipped[@]}" "${devs_picked[@]}") 223daf647bcSMichal Berger 224daf647bcSMichal Berger} 225daf647bcSMichal Berger 2267a1bd398SMichal Bergerodevices() { 2277a1bd398SMichal Berger local bdf 2287a1bd398SMichal Berger 2297a1bd398SMichal Berger type=all gdevices 2307a1bd398SMichal Berger 2317a1bd398SMichal Berger while read -rp "(BDF)> " bdf; do 2327a1bd398SMichal Berger bdf=${bdf,,} 2337a1bd398SMichal Berger if [[ -z $bdf ]]; then 2347a1bd398SMichal Berger return 2357a1bd398SMichal Berger elif [[ -n ${dev_ref["$bdf"]} ]]; then 2367a1bd398SMichal Berger dev_ref["$bdf"]=$((!dev_ref["$bdf"])) 2377a1bd398SMichal Berger fi 2387a1bd398SMichal Berger done 2397a1bd398SMichal Berger} 2407a1bd398SMichal Berger 2417a1bd398SMichal Bergerbdevices() { 2427a1bd398SMichal Berger [[ $os == Linux ]] || return 0 2437a1bd398SMichal Berger 244*2e497261SMichal Berger local bdf driver 2457a1bd398SMichal Berger 2467a1bd398SMichal Berger gdevices 2477a1bd398SMichal Berger 248*2e497261SMichal Berger while read -rp "(BDF)> " bdf; do 249*2e497261SMichal Berger bdf=${bdf,,} 250*2e497261SMichal Berger if [[ -z $bdf ]]; then 2517a1bd398SMichal Berger return 2527a1bd398SMichal Berger fi 2537a1bd398SMichal Berger 254*2e497261SMichal Berger [[ -n ${dev_ref["$bdf"]} ]] || continue 2557a1bd398SMichal Berger 256*2e497261SMichal Berger pdriver "$bdf" 257*2e497261SMichal Berger 258*2e497261SMichal Berger while read -rp "Select driver ($bdf)> " driver; do 259*2e497261SMichal Berger driver=${driver,,} 260*2e497261SMichal Berger if [[ -z $driver ]]; then 261*2e497261SMichal Berger continue 2 262*2e497261SMichal Berger fi 263*2e497261SMichal Berger if [[ $driver == "${pci_bus_driver["$bdf"]}" ]]; then 2647a1bd398SMichal Berger echo "$bdf already bound to $driver" 2657a1bd398SMichal Berger continue 2667a1bd398SMichal Berger fi 267*2e497261SMichal Berger break 268*2e497261SMichal Berger done 2697a1bd398SMichal Berger 270*2e497261SMichal Berger # Try to be nice and silently attempt to load the driver just in case 271*2e497261SMichal Berger modprobe -q "$driver" || true 272*2e497261SMichal Berger 273*2e497261SMichal Berger if yn "$bdf currently bound to ${pci_bus_driver["$bdf"]:-none}. Bind to $driver?"; then 2747a1bd398SMichal Berger linux_bind_driver "$bdf" "$driver" 275*2e497261SMichal Berger return 2767a1bd398SMichal Berger fi 2777a1bd398SMichal Berger done 2787a1bd398SMichal Berger} 2797a1bd398SMichal Berger 280*2e497261SMichal Bergerpdriver() { 281*2e497261SMichal Berger local bdf=$1 282*2e497261SMichal Berger 283*2e497261SMichal Berger cat <<- DRIVER 284*2e497261SMichal Berger 285*2e497261SMichal Berger $bdf: 286*2e497261SMichal Berger main driver: $(collect_driver "$bdf") 287*2e497261SMichal Berger current driver: ${pci_bus_driver["$bdf"]:-none} 288*2e497261SMichal Berger 289*2e497261SMichal Berger DRIVER 290*2e497261SMichal Berger} 291*2e497261SMichal Berger 2927a1bd398SMichal Bergerstatus() { 2937a1bd398SMichal Berger local _os=${os,,} 2947a1bd398SMichal Berger 2957a1bd398SMichal Berger if [[ $(type -t "status_${_os}") == function ]]; then 2967a1bd398SMichal Berger "status_${_os}" 297f01d428bSMichal Berger fi 2> /dev/null 2987a1bd398SMichal Berger} 2997a1bd398SMichal Berger 3007a1bd398SMichal Bergerhugepages() { 3017a1bd398SMichal Berger [[ $os == Linux ]] || return 0 3027a1bd398SMichal Berger local hp 3037a1bd398SMichal Berger 3047a1bd398SMichal Berger while read -rp "('clear' 'even' 'commit' HUGEMEM[=$HUGEMEM MB])> " hp; do 3057a1bd398SMichal Berger hp=${hp,,} 3067a1bd398SMichal Berger if [[ -z $hp ]]; then 3077a1bd398SMichal Berger return 3087a1bd398SMichal Berger elif [[ $hp == clear ]]; then 3097a1bd398SMichal Berger clear_hugepages 3107a1bd398SMichal Berger return 3117a1bd398SMichal Berger elif [[ $hp =~ ^[1-9][0-9]*$ ]]; then 3127a1bd398SMichal Berger NRHUGE="" 3137a1bd398SMichal Berger HUGEMEM=$hp 3147a1bd398SMichal Berger elif [[ $hp == commit ]]; then 3157a1bd398SMichal Berger set_hp 3167a1bd398SMichal Berger configure_linux_hugepages 3177a1bd398SMichal Berger return 3187a1bd398SMichal Berger fi 3197a1bd398SMichal Berger done 3207a1bd398SMichal Berger} 321c97b31f8SMichal Berger 322c97b31f8SMichal Bergerupdate_status() { 323c97b31f8SMichal Berger CMD=reset cache_pci_bus 324c97b31f8SMichal Berger collect_devices 325c97b31f8SMichal Berger} 326