From dde1fede1f832f029742a1d27290cfe252ab1bc5 Mon Sep 17 00:00:00 2001 From: "Thang Q. Nguyen" Date: Thu, 4 Nov 2021 08:30:27 +0000 Subject: meta-ampere: fix shellcheck issues Fix all issues from the shellcheck checked on bash shells under meta-ampere. Tested: Verify the following features: 1. Power control (on,off, cycle, graceful shutdown, hard reset). 2. UART switching. 3. UEFI firmware update. Signed-off-by: Thang Q. Nguyen Change-Id: Idabf839b7521ecadb642230cc8bb3472c787002e --- .../flash/ampere-flash-utils/ampere_flash_bios.sh | 19 +- .../ampere-mac-update/ampere_update_mac.sh | 33 ++-- .../ampere-platform-init/ampere_platform_init.sh | 3 +- .../mtjade-gpio-config/ampere_gpio_utils.sh | 50 +++--- .../platform/mtjade-utils/ampere_host_check.sh | 51 +++--- .../platform/mtjade-utils/ampere_power_util.sh | 191 ++++++++++----------- .../platform/mtjade-utils/gpio-defs.sh | 3 + .../platform/mtjade-utils/gpio-lib.sh | 32 ++-- 8 files changed, 184 insertions(+), 198 deletions(-) (limited to 'meta-ampere/meta-jade/recipes-ampere') diff --git a/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh b/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh index 7a9ace30e..b7f4bc52e 100755 --- a/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh +++ b/meta-ampere/meta-jade/recipes-ampere/flash/ampere-flash-utils/ampere_flash_bios.sh @@ -18,7 +18,7 @@ do_flash () { OFFSET=$1 # Check the PNOR partition available - HOST_MTD=$(cat /proc/mtd | grep "pnor" | sed -n 's/^\(.*\):.*/\1/p') + HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p') if [ -z "$HOST_MTD" ]; then # If the PNOR partition is not available, then bind again driver @@ -26,7 +26,7 @@ do_flash () { echo 1e630000.spi > /sys/bus/platform/drivers/aspeed-smc/bind sleep 2 - HOST_MTD=$(cat /proc/mtd | grep "pnor" | sed -n 's/^\(.*\):.*/\1/p') + HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p') if [ -z "$HOST_MTD" ]; then echo "Fail to probe Host SPI-NOR device" @@ -35,18 +35,17 @@ do_flash () { fi echo "--- Flashing firmware to @/dev/$HOST_MTD offset=$OFFSET" - flashcp -v $IMAGE /dev/$HOST_MTD $OFFSET + flashcp -v "$IMAGE" /dev/"$HOST_MTD" "$OFFSET" } if [ $# -eq 0 ]; then - echo "Usage: $(basename $0) " + echo "Usage: $(basename "$0") " exit 0 fi IMAGE="$1" -if [ ! -f $IMAGE ]; then - echo $IMAGE +if [ ! -f "$IMAGE" ]; then echo "The image file $IMAGE does not exist" exit 1 fi @@ -70,9 +69,7 @@ fi # Switch the host SPI bus to BMC" echo "--- Switch the host SPI bus to BMC." -gpioset 0 226=0 - -if [[ $? -ne 0 ]]; then +if ! gpioset 0 226=0; then echo "ERROR: Switch the host SPI bus to BMC. Please check gpio state" exit 1 fi @@ -82,9 +79,7 @@ do_flash 0x400000 # Switch the host SPI bus to HOST." echo "--- Switch the host SPI bus to HOST." -gpioset 0 226=1 - -if [[ $? -ne 0 ]]; then +if ! gpioset 0 226=1; then echo "ERROR: Switch the host SPI bus to HOST. Please check gpio state" exit 1 fi diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-mac-update/ampere_update_mac.sh b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-mac-update/ampere_update_mac.sh index 4e4d6f3e7..8182b4c8d 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-mac-update/ampere_update_mac.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-mac-update/ampere_update_mac.sh @@ -5,43 +5,44 @@ ETHERNET_INTERFACE="eth1" ETHERNET_NCSI="eth0" ENV_ETH="eth1addr" -ENV_MAC_ADDR=`fw_printenv | grep $ENV_ETH` +ENV_MAC_ADDR=$(fw_printenv | grep $ENV_ETH) # Workaround to dhcp NC-SI eth0 interface when BMC boot up ifconfig ${ETHERNET_NCSI} down ifconfig ${ETHERNET_NCSI} up # Read FRU Board Custom Field 1 to get the MAC address -CUSTOM_FIELD_1=`busctl get-property xyz.openbmc_project.FruDevice /xyz/openbmc_project/FruDevice/Mt_Jade_Motherboard xyz.openbmc_project.FruDevice BOARD_INFO_AM1` -MAC_ADDR=`echo $CUSTOM_FIELD_1 | cut -d "\"" -f 2` +CUSTOM_FIELD_1=$(busctl get-property xyz.openbmc_project.FruDevice /xyz/openbmc_project/FruDevice/Mt_Jade_Motherboard xyz.openbmc_project.FruDevice BOARD_INFO_AM1) +MAC_ADDR=$(echo "$CUSTOM_FIELD_1" | cut -d "\"" -f 2) # Check if BMC MAC address is exported if [ -z "${MAC_ADDR}" ]; then - echo "ERROR: No BMC MAC address is detected from FRU Inventory information!" - # Return 1 so that systemd knows the service failed to start - exit 1 + echo "ERROR: No BMC MAC address is detected from FRU Inventory information!" + # Return 1 so that systemd knows the service failed to start + exit 1 fi # Check if BMC MAC address is exported if [[ $ENV_MAC_ADDR =~ $MAC_ADDR ]]; then - echo "WARNING: BMC MAC address already exist!" - exit 0 + echo "WARNING: BMC MAC address already exist!" + exit 0 fi # Request to update the MAC address -fw_setenv ${ENV_ETH} ${MAC_ADDR} +fw_setenv ${ENV_ETH} "${MAC_ADDR}" -if [[ $? -ne 0 ]]; then - echo "ERROR: Fail to set MAC address to ${ENV_ETH}" - exit 1 +if fw_setenv ${ENV_ETH} "${MAC_ADDR}"; +then + echo "ERROR: Fail to set MAC address to ${ENV_ETH}" + exit 1 fi # Request to restart the service ifconfig ${ETHERNET_INTERFACE} down -ifconfig ${ETHERNET_INTERFACE} hw ether ${MAC_ADDR} -if [[ $? -ne 0 ]]; then - echo "ERROR: Can not update MAC ADDR to ${ETHERNET_INTERFACE}" - exit 1 +if ! ifconfig ${ETHERNET_INTERFACE} hw ether "${MAC_ADDR}"; +then + echo "ERROR: Can not update MAC ADDR to ${ETHERNET_INTERFACE}" + exit 1 fi ifconfig ${ETHERNET_INTERFACE} up diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh index a2578fa2f..c3772fb9a 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/ampere-platform-init/ampere_platform_init.sh @@ -1,5 +1,6 @@ #!/bin/bash +# shellcheck source=/dev/null source /usr/sbin/gpio-lib.sh # GPIOAC3 BMC_SPI0_BACKUP_SEL Boot from MAIN SPI-HOST @@ -29,7 +30,7 @@ gpio_configure_output 229 1 # ======================================================= # Below GPIOs are controlled by other services so just # initialize in A/C power only. -cmdline=`cat /proc/cmdline` +cmdline=$(cat /proc/cmdline) if [[ $cmdline == *resetreason=power* ]]; then # BMC_GPIOR2_EXT_HIGHTEMP_L gpio_configure_output 138 1 diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere_gpio_utils.sh b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere_gpio_utils.sh index 8e4f455bf..1a098f446 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere_gpio_utils.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-gpio-config/ampere_gpio_utils.sh @@ -1,43 +1,45 @@ #!/bin/bash + +# shellcheck source=/dev/null source /usr/sbin/gpio-defs.sh source /usr/sbin/gpio-lib.sh function usage() { - echo "usage: ampere_gpio_utils.sh [power] [on|off]"; + echo "usage: ampere_gpio_utils.sh [power] [on|off]"; } set_gpio_power_off() { - echo "Setting GPIO before Power off" - gpio_configure_output $OCP_AUX_PWREN 1 - gpio_configure_output $OCP_MAIN_PWREN 0 - gpio_configure_output $SPI0_PROGRAM_SEL 0 + echo "Setting GPIO before Power off" + gpio_configure_output "$OCP_AUX_PWREN" 1 + gpio_configure_output "$OCP_MAIN_PWREN" 0 + gpio_configure_output "$SPI0_PROGRAM_SEL" 0 } set_gpio_power_on() { - echo "Setting GPIO before Power on" - gpio_configure_output $OCP_AUX_PWREN 1 - gpio_configure_output $OCP_MAIN_PWREN 1 - gpio_configure_output $SPI0_PROGRAM_SEL 1 - gpio_configure_output $SPI0_BACKUP_SEL 0 + echo "Setting GPIO before Power on" + gpio_configure_output "$OCP_AUX_PWREN" 1 + gpio_configure_output "$OCP_MAIN_PWREN" 1 + gpio_configure_output "$SPI0_PROGRAM_SEL" 1 + gpio_configure_output "$SPI0_BACKUP_SEL" 0 } if [ $# -lt 2 ]; then - echo "Total number of parameter=$#" - echo "Insufficient parameter" - usage; - exit 0; + echo "Total number of parameter=$#" + echo "Insufficient parameter" + usage; + exit 0; fi -if [ $1 == "power" ]; then - if [ $2 == "on" ]; then - set_gpio_power_on - elif [ $2 == "off" ]; then - set_gpio_power_off - fi - exit 0; +if [ "$1" == "power" ]; then + if [ "$2" == "on" ]; then + set_gpio_power_on + elif [ "$2" == "off" ]; then + set_gpio_power_off + fi + exit 0; else - echo "Invalid parameter1=$1" - usage; - exit 0; + echo "Invalid parameter1=$1" + usage; + exit 0; fi exit 0; diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_host_check.sh b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_host_check.sh index 9eeeeca5a..024336d20 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_host_check.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_host_check.sh @@ -1,45 +1,38 @@ #!/bin/bash +# shellcheck source=/dev/null source /usr/sbin/gpio-defs.sh source /usr/sbin/gpio-lib.sh -host_status() { - st=$(busctl get-property xyz.openbmc_project.State.Host /xyz/openbmc_project/state/host0 xyz.openbmc_project.State.Host CurrentHostState | cut -d"." -f6) - if [ "$st" == "Running\"" ]; then - echo "on" - else - echo "off" - fi -} - createFile=$1 -setState=$2 -if [ $(host_status) == "on" ]; then - exit 0 +# Check current Host status. Do nothing when the Host is currently ON +st=$(busctl get-property xyz.openbmc_project.State.Host \ + /xyz/openbmc_project/state/host0 xyz.openbmc_project.State.Host \ + CurrentHostState | cut -d"." -f6) +if [ "$st" == "Running\"" ]; then + exit 0 fi # Time out to check S0_FW_BOOT_OK is 60 seconds cnt=60 val=0 -while [ $cnt -gt 0 ]; +while [ "$cnt" -gt 0 ]; do - val=$(gpio_get_val $S0_CPU_FW_BOOT_OK) - cnt=$((cnt - 1)) - echo "$cnt S0_CPU_FW_BOOT_OK = $val" - if [ $val == 1 ]; then - # Sleep 5 second before the host is ready - sleep 5 - if [ $createFile == 1 ]; then - if [ ! -d "/run/openbmc" ]; then - mkdir -p /run/openbmc - fi - echo "Creating /run/openbmc/host@0-on" - touch /run/openbmc/host@0-on - fi - exit 0 - fi - sleep 1 + val=$(gpio_get_val "$S0_CPU_FW_BOOT_OK") + cnt=$((cnt - 1)) + echo "$cnt S0_CPU_FW_BOOT_OK = $val" + if [ "$val" == 1 ]; then + # Sleep 5 second before the host is ready + sleep 5 + if [ "$createFile" == 1 ]; then + mkdir -p /run/openbmc + echo "Creating /run/openbmc/host@0-on" + touch /run/openbmc/host@0-on + fi + exit 0 + fi + sleep 1 done exit 1 diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_power_util.sh b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_power_util.sh index 2c8ba3d91..d9ca2ed08 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_power_util.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/ampere_power_util.sh @@ -1,131 +1,120 @@ #!/bin/bash -#ampere_platform_config.sh is platform configuration file + +# shellcheck source=/dev/null source /usr/sbin/gpio-defs.sh # Usage of this utility function usage() { - echo "usage: power-util mb [status|shutdown_ack|force_reset|soft_off]"; + echo "Usage:" + echo " ampere_power_util.sh mb [status|shutdown_ack|force_reset|soft_off]"; } power_status() { - st=$(busctl get-property xyz.openbmc_project.State.Chassis /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis CurrentPowerState | cut -d"." -f6) - if [ "$st" == "On\"" ]; then - echo "on" - else - echo "off" - fi + st=$(busctl get-property xyz.openbmc_project.State.Chassis /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis CurrentPowerState | cut -d"." -f6) + if [ "$st" == "On\"" ]; then + echo "on" + else + echo "off" + fi } shutdown_ack() { - if [ -f "/run/openbmc/host@0-softpoweroff" ]; then - echo "Receive shutdown ACK triggered after softportoff the host." - touch /run/openbmc/host@0-softpoweroff-shutdown-ack - else - echo "Receive shutdown ACK triggered" - sleep 3 - systemctl start obmc-chassis-poweroff@0.target - fi + if [ -f "/run/openbmc/host@0-softpoweroff" ]; then + echo "Receive shutdown ACK triggered after softportoff the host." + touch /run/openbmc/host@0-softpoweroff-shutdown-ack + else + echo "Receive shutdown ACK triggered" + sleep 3 + systemctl start obmc-chassis-poweroff@0.target + fi } soft_off() { - # Trigger shutdown_req - touch /run/openbmc/host@0-softpoweroff - gpioset -l $GPIO_CHIP0_IDX $S0_SHD_REQ_L=1 - sleep 1s - gpioset -l $GPIO_CHIP0_IDX $S0_SHD_REQ_L=0 + # Trigger shutdown_req + touch /run/openbmc/host@0-softpoweroff + gpioset -l 0 "$S0_SHD_REQ_L"=1 + sleep 1s + gpioset -l 0 "$S0_SHD_REQ_L"=0 - # Wait for shutdown_ack from the host in 30 seconds - cnt=30 - while [ $cnt -gt 0 ]; - do - # Wait for SHUTDOWN_ACK and create the host@0-softpoweroff-shutdown-ack - if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then - break - fi - sleep 1 - cnt=$((cnt - 1)) - done - # Softpoweroff is successed - sleep 2 - rm -rf /run/openbmc/host@0-softpoweroff - if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then - rm -rf /run/openbmc/host@0-softpoweroff-shutdown-ack - fi - echo 0 + # Wait for shutdown_ack from the host in 30 seconds + cnt=30 + while [ $cnt -gt 0 ]; + do + # Wait for SHUTDOWN_ACK and create the host@0-softpoweroff-shutdown-ack + if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then + break + fi + sleep 1 + cnt=$((cnt - 1)) + done + # Softpoweroff is successed + sleep 2 + rm -rf /run/openbmc/host@0-softpoweroff + if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then + rm -rf /run/openbmc/host@0-softpoweroff-shutdown-ack + fi + echo 0 } force_reset() { - if [ -f "/run/openbmc/host@0-softpoweroff" ]; then - # In graceful host reset, after trigger os shutdown, - # the phosphor-state-manager will call force-warm-reset - # in this case the force_reset should wait for shutdown_ack from host - cnt=30 - while [ $cnt -gt 0 ]; - do - if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then - break - fi - echo "Waiting for shutdown-ack count down $cnt" - sleep 1 - cnt=$((cnt - 1)) - done - # The host OS is failed to shutdown - if [ $cnt == 0 ]; then - echo "Shutdown-ack time out after 30s." - exit 0 - fi - fi - echo "Triggering sysreset pin" - gpioset -l $GPIO_CHIP0_IDX $S0_SYSRESET_L=1 - sleep 1 - gpioset -l $GPIO_CHIP0_IDX $S0_SYSRESET_L=0 + if [ -f "/run/openbmc/host@0-softpoweroff" ]; then + # In graceful host reset, after trigger os shutdown, + # the phosphor-state-manager will call force-warm-reset + # in this case the force_reset should wait for shutdown_ack from host + cnt=30 + while [ $cnt -gt 0 ]; + do + if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then + break + fi + echo "Waiting for shutdown-ack count down $cnt" + sleep 1 + cnt=$((cnt - 1)) + done + # The host OS is failed to shutdown + if [ $cnt == 0 ]; then + echo "Shutdown-ack time out after 30s." + exit 0 + fi + fi + echo "Triggering sysreset pin" + gpioset -l 0 "$S0_SYSRESET_L"=1 + sleep 1 + gpioset -l 0 "$S0_SYSRESET_L"=0 } if [ $# -lt 2 ]; then - echo "Total number of parameter=$#" - echo "Insufficient parameter" - usage; - exit 0; + echo "Total number of parameter=$#" + echo "Insufficient parameter" + usage; + exit 0; fi -if [ $1 != "mb" ]; then - echo "Invalid parameter1=$1" - usage; - exit 0; +if [ "$1" != "mb" ]; then + echo "Invalid parameter1=$1" + usage; + exit 0; fi -# check if power guard enabled -dir="/run/systemd/system/" -file="reboot-guard.conf" -units=("reboot" "poweroff" "halt") -for unit in "${units[@]}"; do - if [ -f ${dir}${unit}.target.d/${file} ]; then - echo "PowerGuard enabled, cannot do power control, exit!!!" - exit -1 - fi -done - -if [ ! -d "/run/openbmc/" ]; then - mkdir -p "/run/openbmc/" -fi +mkdir -p /run/openbmc/ -if [ $2 == "shutdown_ack" ]; then - shutdown_ack -elif [ $2 == "status" ]; then - power_status -elif [ $2 == "force_reset" ]; then - force_reset -elif [ $2 == "soft_off" ]; then - ret=$(soft_off) - if [ $ret == 0 ]; then - echo "The host is already softoff" - else - echo "Failed to softoff the host" - fi - exit $ret; +if [ "$2" == "shutdown_ack" ]; then + shutdown_ack +elif [ "$2" == "status" ]; then + power_status +elif [ "$2" == "force_reset" ]; then + force_reset +elif [ "$2" == "soft_off" ]; then + ret=$(soft_off) + if [ "$ret" == 0 ]; then + echo "The host is already softoff" + else + echo "Failed to softoff the host" + fi + exit "$ret"; else - echo "Invalid parameter2=$2" - usage; + echo "Invalid parameter2=$2" + usage; fi exit 0; diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-defs.sh b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-defs.sh index 7c887d409..fc0edd6fc 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-defs.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-defs.sh @@ -1,3 +1,6 @@ +#!/bin/sh + +# shellcheck disable=SC2034 # Index of GPIO device in gpioget/gpioset GPIO_CHIP0_IDX=0 GPIO_CHIP1_IDX=1 diff --git a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-lib.sh b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-lib.sh index 8d1aa61d7..c8721fe97 100644 --- a/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-lib.sh +++ b/meta-ampere/meta-jade/recipes-ampere/platform/mtjade-utils/gpio-lib.sh @@ -1,31 +1,33 @@ #!/bin/bash + +# shellcheck source=/dev/null source /usr/sbin/gpio-defs.sh function gpio_number() { - GPIO_BASE=$(cat /sys/class/gpio/gpiochip$GPIO_CHIP0_BASE/base) - echo $((${GPIO_BASE} + $1)) + GPIO_BASE=$(cat /sys/class/gpio/gpiochip"$GPIO_CHIP0_BASE"/base) + echo $((GPIO_BASE + $1)) } # Configure GPIO as output and set its value function gpio_configure_output() { - gpioId=$(gpio_number $1) - echo $gpioId > /sys/class/gpio/export - echo out > /sys/class/gpio/gpio${gpioId}/direction - echo $2 > /sys/class/gpio/gpio${gpioId}/value - echo $gpioId > /sys/class/gpio/unexport + gpioId=$(gpio_number "$1") + echo "$gpioId" > /sys/class/gpio/export + echo out > /sys/class/gpio/gpio"${gpioId}"/direction + echo "$2" > /sys/class/gpio/gpio"${gpioId}"/value + echo "$gpioId" > /sys/class/gpio/unexport } function gpio_get_val() { - gpioId=$(gpio_number $1) - echo $gpioId > /sys/class/gpio/export - echo $(cat /sys/class/gpio/gpio$gpioId/value) - echo $gpioId > /sys/class/gpio/unexport + gpioId=$(gpio_number "$1") + echo "$gpioId" > /sys/class/gpio/export + cat /sys/class/gpio/gpio"$gpioId"/value + echo "$gpioId" > /sys/class/gpio/unexport } # Configure GPIO as input function gpio_configure_input() { - gpioId=$(gpio_number $1) - echo $gpioId > /sys/class/gpio/export - echo "in" > /sys/class/gpio/gpio${gpioId}/direction - echo $gpioId > /sys/class/gpio/unexport + gpioId=$(gpio_number "$1") + echo "$gpioId" > /sys/class/gpio/export + echo "in" > /sys/class/gpio/gpio"${gpioId}"/direction + echo "$gpioId" > /sys/class/gpio/unexport } -- cgit v1.2.3