1#!/bin/bash 2# 3# Power Control tool 4# Enable/disable AC relay 5# On/off System by step moter to press power key 6 7export PATH=$PATH:/usr/sbin:/usr/libexec 8 9# shellcheck source=meta-facebook/meta-bletchley/recipes-bletchley/plat-tools/files/bletchley-common-functions 10source /usr/libexec/bletchley-common-functions 11 12DELAY_POWER_ON="0.5" 13DELAY_POWER_OFF="10" 14DELAY_POWER_RECOVERY_MODE="10" 15POWER_BTN_TIMEOUT_SEC=10 16 17REV_EVT="EVT" 18REV_DVT="DVT" 19REV_UNKNOW="UNKNOW" 20 21DBUS_HOST_ST_ON="xyz.openbmc_project.State.Host.HostState.Running" 22DBUS_HOST_ST_OFF="xyz.openbmc_project.State.Host.HostState.Off" 23 24HOST_ST_UNKNOW="Unknow" 25HOST_ST_ON="On" 26HOST_ST_OFF="Off" 27HOST_ST_SLEEP="Sleep" 28HOST_ST_DFU="DFU" 29HOST_ST_RECOVERY="Recovery" 30HOST_AC_ON="AC On" 31HOST_AC_OFF="AC Off" 32 33ACTION_ON="on" 34ACTION_OFF="off" 35ACTION_DFU="dfu" 36ACTION_RECOVERY="recovery" 37ACTION_CYCLE="cycle" 38ACTION_RESET="reset" 39ACTION_AC_ON="ac-on" 40ACTION_AC_OFF="ac-off" 41ACTION_STATUS="status" 42ACTION_BOOT_MODE="boot-from-bootmode" 43 44VALID_SLED_ACTIONS=" 45 $ACTION_ON 46 $ACTION_OFF 47 $ACTION_AC_ON 48 $ACTION_AC_OFF 49 $ACTION_STATUS 50 $ACTION_DFU 51 $ACTION_RECOVERY 52 $ACTION_CYCLE 53 $ACTION_RESET 54 $ACTION_BOOT_MODE 55" 56 57BOOT_MODE_REGULAR="\"xyz.openbmc_project.Control.Boot.Mode.Modes.Regular\"" 58BOOT_MODE_SAFE="\"xyz.openbmc_project.Control.Boot.Mode.Modes.Safe\"" 59BOOT_MODE_SETUP="\"xyz.openbmc_project.Control.Boot.Mode.Modes.Setup\"" 60 61function is_valid_sled_action() 62{ 63 local ACTION=$1 64 for i in $VALID_SLED_ACTIONS 65 do 66 if [ "$i" = "$ACTION" ]; then 67 return 0 68 fi 69 done 70 return 1 71} 72 73function get_board_rev() 74{ 75 local rev_id0 76 local rev_id1 77 local rev_id2 78 local rev_val 79 80 rev_id0=$(get_gpio "REV_ID0") 81 rev_id1=$(get_gpio "REV_ID1") 82 rev_id2=$(get_gpio "REV_ID2") 83 rev_val=$((rev_id0+(rev_id1<<1)+(rev_id2<<2))) 84 85 case $rev_val in 86 0) 87 echo "$REV_EVT" 88 ;; 89 1) 90 echo "$REV_DVT" 91 ;; 92 *) 93 echo "$REV_UNKNOW" 94 return 1 95 ;; 96 esac 97 98 return 0 99} 100 101function trigger_power_button() 102{ 103 local sled_num=$1 104 local delay_time=$2 105 106 #SLED{N}_MS_DETECT1 (initial position) 107 GPIO_DETECT_PIN1="SLED${sled_num}_MS_DETECT1" 108 #SLED{N}_MS_DETECT0 (MAC position) 109 GPIO_DETECT_PIN0="SLED${sled_num}_MS_DETECT0" 110 111 echo "Motor go forward to press Power key" 112 motor-ctrl "sled${sled_num}" f >/dev/null 113 wait_gpio_falling "${GPIO_DETECT_PIN0}" "$POWER_BTN_TIMEOUT_SEC" 114 motor-ctrl "sled${sled_num}" s >/dev/null 115 116 if [ "$(get_gpio "$GPIO_DETECT_PIN0")" -eq 0 ];then 117 echo "Power key switch triggered" 118 echo "Press power key for Sled${1} ${delay_time} seconds..." 119 sleep "$delay_time" 120 else 121 echo "Power key switch not trigger, back motor to initial position" 122 fi 123 124 motor-ctrl "sled${sled_num}" r >/dev/null 125 wait_gpio_falling "${GPIO_DETECT_PIN1}" "$POWER_BTN_TIMEOUT_SEC" 126 motor-ctrl "sled${sled_num}" s >/dev/null 127 if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ];then 128 echo "Motor reverse to initial position successful" 129 else 130 echo "Initial position switch not trigger, force stop motor" 131 fi 132} 133 134function release_power_button() 135{ 136 local sled_num=$1 137 GPIO_DETECT_PIN1="SLED${sled_num}_MS_DETECT1" 138 139 if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ]; then 140 echo "Motor at initial position already" 141 return 0 142 fi 143 144 motor-ctrl "sled${sled_num}" r >/dev/null 145 wait_gpio_falling "${GPIO_DETECT_PIN1}" "$POWER_BTN_TIMEOUT_SEC" 146 motor-ctrl "sled${sled_num}" s >/dev/null 147 if [ "$(get_gpio "$GPIO_DETECT_PIN1")" -eq 0 ];then 148 echo "Motor reverse to initial position successful" 149 return 0 150 fi 151 152 echo "Error: Initial position switch not trigger" 153 return 1 154} 155 156function press_power_button() 157{ 158 local sled_num=$1 159 160 GPIO_DETECT_PIN0="SLED${sled_num}_MS_DETECT0" 161 162 echo "Motor go forward to press Power button" 163 motor-ctrl "sled${sled_num}" f >/dev/null 164 wait_gpio_falling "${GPIO_DETECT_PIN0}" "$POWER_BTN_TIMEOUT_SEC" 165 motor-ctrl "sled${sled_num}" s >/dev/null 166 167 if [ "$(get_gpio "$GPIO_DETECT_PIN0")" -eq 0 ];then 168 echo "Power button switch triggered" 169 return 0 170 fi 171 172 echo "Error: Power button switch not trigger" 173 return 1 174} 175 176#Get i2c bus number for sledN 177function get_bus_num() 178{ 179 SLED_NUM=$1 180 local bus=0 181 #Mapping Sled number 1~6 to i2c bus number 0~5 182 if [[ "$SLED_NUM" = [1-6] ]]; then 183 bus=$(( SLED_NUM - 1 )) 184 fi 185 echo "$bus" 186} 187 188function get_ac_status() 189{ 190 i2c_bus=$(get_bus_num "$1") 191 p1_output_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x03) 192 p1_config_reg=$(i2cget -f -y "$i2c_bus" 0x76 0x07) 193 host_pwr="$(( (p1_output_reg & 0x80)>>7 ))" 194 is_output="$(( (~p1_config_reg & 0x80)>>7 ))" 195 196 if [ "$(( host_pwr & is_output ))" -eq 1 ];then 197 echo "$HOST_AC_ON" 198 else 199 echo "$HOST_AC_OFF" 200 fi 201} 202 203function get_host_status_dbus() 204{ 205 local sled_num=$1 206 local object="/xyz/openbmc_project/state/host${sled_num}" 207 local service="xyz.openbmc_project.State.Host${sled_num}" 208 local interface="xyz.openbmc_project.State.Host" 209 local property="CurrentHostState" 210 local host_state 211 212 host_state=$(busctl get-property "$service" "$object" "$interface" "$property" | cut -d '"' -f2) 213 214 if [ "$host_state" = "$DBUS_HOST_ST_ON" ]; then 215 echo "$HOST_ST_ON" 216 elif [ "$host_state" = "$DBUS_HOST_ST_OFF" ]; then 217 echo "$HOST_ST_OFF" 218 else 219 echo "$HOST_ST_UNKNOW" 220 return 1 221 fi 222 223 return 0 224} 225 226function get_addr_from_dts_aliases() 227{ 228 local node_address 229 node_address=$(awk -F '@' '{printf $2}' /sys/firmware/devicetree/base/aliases/"$1") 230 echo "$node_address" 231} 232 233function get_host_status_mdio() 234{ 235 local SLED_NUM=$1 236 local MDIO_BUS 237 238 MDIO_BUS="$(get_addr_from_dts_aliases mdio0).mdio-1" 239 240 declare -a PORT_MAP=(0 3 2 1 7 6 5) 241 242 # check /dev/mem 243 if ! create_dev_mem; then 244 return 1 245 fi 246 247 local CHECK_CNT=0 248 local MDIO_ERR_CNT=0 249 local CUR_HOST_ST=$HOST_ST_UNKNOW 250 local SLED_LAST_ACTION 251 252 if [ -f /tmp/sled"${SLED_NUM}"-last-action ]; then 253 SLED_LAST_ACTION=$(cat /tmp/sled"${SLED_NUM}"-last-action) 254 fi 255 256 while true 257 do 258 if POST_ST_VAL=$(mdio "$MDIO_BUS" phy "${PORT_MAP[SLED_NUM]}" 0); then 259 if [ $((POST_ST_VAL&16#0800)) -eq $((16#0000)) ]; then 260 case $SLED_LAST_ACTION in 261 "$ACTION_DFU") 262 TMP_HOST_ST="$HOST_ST_DFU" 263 ;; 264 *) 265 TMP_HOST_ST="$HOST_ST_OFF" 266 ;; 267 esac 268 elif [ $((POST_ST_VAL&16#0A00)) -eq $((16#0A00)) ]; then 269 TMP_HOST_ST="$HOST_ST_ON" 270 case $SLED_LAST_ACTION in 271 "$ACTION_RECOVERY") 272 TMP_HOST_ST="$HOST_ST_RECOVERY" 273 ;; 274 *) 275 TMP_HOST_ST="$HOST_ST_ON" 276 ;; 277 esac 278 elif [ $((POST_ST_VAL&16#0900)) -eq $((16#0900)) ]; then 279 TMP_HOST_ST="$HOST_ST_SLEEP" 280 else 281 TMP_HOST_ST="$HOST_ST_UNKNOW" 282 fi 283 284 if [ "$CUR_HOST_ST" == "$TMP_HOST_ST" ]; then 285 CHECK_CNT=$((CHECK_CNT+1)) 286 else 287 CUR_HOST_ST=$TMP_HOST_ST 288 CHECK_CNT=0 289 fi 290 291 if [ "$CHECK_CNT" -ge 5 ]; then 292 echo "$CUR_HOST_ST" 293 break 294 fi 295 else 296 MDIO_ERR_CNT=$((MDIO_ERR_CNT+1)) 297 if [ "$MDIO_ERR_CNT" -ge 5 ]; then 298 echo "$HOST_ST_UNKNOW" 299 return 1 300 fi 301 fi 302 done 303 304 return 0 305} 306 307function get_host_status() 308{ 309 local sled_num=$1 310 311 if [ "$(get_ac_status "$SLED_NUM")" == "$HOST_AC_OFF" ];then 312 echo "$HOST_AC_OFF" 313 return 0 314 fi 315 316 if [ "$(get_board_rev)" = "$REV_EVT" ]; then 317 get_host_status_dbus "$sled_num" 318 else 319 get_host_status_mdio "$sled_num" 320 fi 321 return $? 322} 323 324function get_host_bootmode() 325{ 326 local BUS_NAME="xyz.openbmc_project.Settings" 327 local OBJ_PATH="/xyz/openbmc_project/control/host${1}/boot" 328 local INTF_NAME="xyz.openbmc_project.Control.Boot.Mode" 329 busctl get-property "${BUS_NAME}" "${OBJ_PATH}" "${INTF_NAME}" BootMode | awk '{print $2}' 330} 331 332function do_action_reset() 333{ 334 # 1. Power off 335 # 2. Power on 336 337 local SLED_NUM=$1 338 local CUR_ST=$2 339 340 if [ "$CUR_ST" != "$HOST_ST_OFF" ]; then 341 do_action_off "$SLED_NUM" 342 else 343 echo "sled${SLED_NUM}: already powered off" 344 fi 345 346 sleep 3 347 do_action_on "$SLED_NUM" 348} 349 350function do_action_cycle() 351{ 352 # 1. AC off 353 # 2. AC on 354 # 3. Power on 355 356 local SLED_NUM=$1 357 358 do_action_ac_off "$SLED_NUM" 359 sleep 3 360 do_action_ac_on "$SLED_NUM" 361 sleep 3 362 do_action_on "$SLED_NUM" 363} 364 365function do_action_ac_on() 366{ 367 local SLED_NUM=$1 368 echo "sled${SLED_NUM}: turn on AC" 369 set_gpio "power-host${SLED_NUM}" 1 370 sleep 3 # Newer versions of the managed system needs 3 second delay 371 echo "$ACTION_AC_ON" > "/tmp/sled${SLED_NUM}-last-action" 372} 373 374function do_action_ac_off() 375{ 376 local SLED_NUM=$1 377 echo "sled${SLED_NUM}: turn off AC" 378 set_gpio "power-host${SLED_NUM}" 0 379 echo "$ACTION_AC_OFF" > "/tmp/sled${SLED_NUM}-last-action" 380} 381 382function do_action_on() 383{ 384 local SLED_NUM=$1 385 echo "sled${SLED_NUM}: power on host" 386 trigger_power_button "$SLED_NUM" "$DELAY_POWER_ON" 387 sleep 10 # Mac mini need about 10 second to stable link status 388 echo "$ACTION_ON" > "/tmp/sled${SLED_NUM}-last-action" 389} 390 391function do_action_off() 392{ 393 local SLED_NUM=$1 394 echo "sled${SLED_NUM}: power off host" 395 trigger_power_button "$SLED_NUM" "$DELAY_POWER_OFF" 396 echo "$ACTION_OFF" > "/tmp/sled${SLED_NUM}-last-action" 397} 398 399function do_action_recovery() 400{ 401 local SLED_NUM=$1 402 echo "sled${SLED_NUM}: trigger host recovery mode" 403 trigger_power_button "$SLED_NUM" "$DELAY_POWER_RECOVERY_MODE" 404 echo "$ACTION_RECOVERY" > "/tmp/sled${SLED_NUM}-last-action" 405} 406 407function do_action_dfu() 408{ 409 local SLED_NUM=$1 410 echo "sled${SLED_NUM}: trigger host dfu mode" 411 412 # turn ac off, and hold for 25 seconds 413 do_action_ac_off "$SLED_NUM" 414 sleep 25 415 416 # press power button 417 echo "SLED$SLED_NUM: pressing power button" 418 if ! press_power_button "$SLED_NUM"; then 419 echo "SLED$SLED_NUM: press power button failed" 420 echo "SLED$SLED_NUM: releasing power button" 421 release_power_button "$SLED_NUM" 422 return 1 423 fi 424 sleep 1 425 426 # turn ac on 427 echo "SLED$SLED_NUM: turn ac-on" 428 do_action_ac_on "$SLED_NUM" 429 sleep 3 430 431 # release power button 432 echo "SLED$SLED_NUM: releasing host power button" 433 if ! release_power_button "$SLED_NUM"; then 434 echo "SLED$SLED_NUM: release power button failed" 435 return 1 436 fi 437 echo "$ACTION_DFU" > "/tmp/sled${SLED_NUM}-last-action" 438} 439 440function host_state_on_action_handler() 441{ 442 local SLED_NUM=$1 443 local ACTION=$2 444 445 case $ACTION in 446 "$ACTION_OFF") 447 do_action_off "$SLED_NUM" 448 ;; 449 "$ACTION_AC_OFF") 450 do_action_ac_off "$SLED_NUM" 451 ;; 452 "$ACTION_RESET") 453 do_action_reset "$SLED_NUM" "$HOST_ST_ON" 454 ;; 455 "$ACTION_CYCLE") 456 do_action_cycle "$SLED_NUM" 457 ;; 458 "$ACTION_ON") 459 echo "already on" 460 ;; 461 *) 462 echo "Invalid action ($ACTION) for current host state (On)" 463 return 1 464 ;; 465 esac 466} 467 468function host_state_sleep_action_handler() 469{ 470 local SLED_NUM=$1 471 local ACTION=$2 472 473 case $ACTION in 474 "$ACTION_ON") 475 do_action_on "$SLED_NUM" 476 ;; 477 "$ACTION_OFF") 478 do_action_off "$SLED_NUM" 479 ;; 480 "$ACTION_AC_OFF") 481 do_action_ac_off "$SLED_NUM" 482 ;; 483 "$ACTION_RESET") 484 do_action_reset "$SLED_NUM" "$HOST_ST_ON" 485 ;; 486 "$ACTION_CYCLE") 487 do_action_cycle "$SLED_NUM" 488 ;; 489 *) 490 echo "Invalid action ($ACTION) for current host state (Sleep)" 491 return 1 492 ;; 493 esac 494} 495 496function host_state_off_action_handler() 497{ 498 local SLED_NUM=$1 499 local ACTION=$2 500 501 case $ACTION in 502 "$ACTION_ON") 503 do_action_on "$SLED_NUM" 504 ;; 505 "$ACTION_RECOVERY") 506 do_action_recovery "$SLED_NUM" 507 ;; 508 "$ACTION_DFU") 509 do_action_dfu "$SLED_NUM" 510 ;; 511 "$ACTION_AC_OFF") 512 do_action_ac_off "$SLED_NUM" 513 ;; 514 "$ACTION_RESET") 515 do_action_reset "$SLED_NUM" "$HOST_ST_ON" 516 ;; 517 "$ACTION_CYCLE") 518 do_action_cycle "$SLED_NUM" 519 ;; 520 "$ACTION_OFF") 521 echo "already off" 522 ;; 523 *) 524 echo "Invalid action ($ACTION) for current host state (Off)" 525 return 1 526 ;; 527 esac 528} 529 530function host_state_ac_off_action_handler() 531{ 532 local SLED_NUM=$1 533 local ACTION=$2 534 535 case $ACTION in 536 "$ACTION_AC_ON") 537 do_action_ac_on "$SLED_NUM" 538 ;; 539 "$ACTION_DFU") 540 do_action_dfu "$SLED_NUM" 541 ;; 542 "$ACTION_AC_OFF") 543 echo "sled${SLED_NUM}: already ac off" 544 return 1 545 ;; 546 "$ACTION_CYCLE") 547 do_action_reset "$SLED_NUM" 548 ;; 549 *) 550 echo "Invalid action ($ACTION) for current host state (AC Off)" 551 return 1 552 ;; 553 esac 554} 555 556function host_state_ac_on_action_handler() 557{ 558 local SLED_NUM=$1 559 local ACTION=$2 560 561 case $ACTION in 562 "$ACTION_AC_OFF") 563 do_action_ac_off "$SLED_NUM" 564 ;; 565 "$ACTION_DFU") 566 do_action_dfu "$SLED_NUM" 567 ;; 568 "$ACTION_CYCLE") 569 do_action_cycle "$SLED_NUM" 570 ;; 571 *) 572 echo "sled${SLED_NUM}: already ac on" 573 return 1 574 ;; 575 esac 576} 577 578function host_state_recovery_action_handler() 579{ 580 local SLED_NUM=$1 581 local ACTION=$2 582 583 case $ACTION in 584 "$ACTION_OFF") 585 do_action_off "$SLED_NUM" 586 ;; 587 "$ACTION_AC_OFF") 588 do_action_ac_off "$SLED_NUM" 589 ;; 590 "$ACTION_RESET") 591 do_action_reset "$SLED_NUM" "$HOST_ST_ON" 592 ;; 593 "$ACTION_CYCLE") 594 do_action_cycle "$SLED_NUM" 595 ;; 596 *) 597 echo "Invalid action ($ACTION) for current host state (Recovery)" 598 return 1 599 ;; 600 esac 601} 602 603function host_state_dfu_action_handler() 604{ 605 local SLED_NUM=$1 606 local ACTION=$2 607 608 case $ACTION in 609 "$ACTION_AC_OFF") 610 do_action_ac_off "$SLED_NUM" 611 ;; 612 "$ACTION_CYCLE") 613 do_action_cycle "$SLED_NUM" 614 ;; 615 *) 616 echo "Invalid action ($ACTION) for current host state (DFU)" 617 return 1 618 ;; 619 esac 620} 621 622function create_dev_mem() 623{ 624 CHECK_CNT=0 625 while true 626 do 627 CHECK_CNT=$((CHECK_CNT+1)) 628 if [ -c /dev/mem ]; then 629 # /dev/mem already exist 630 return 0 631 elif mknod /dev/mem c 1 1; then 632 # mknod success 633 return 0 634 elif [ "$CHECK_CNT" -ge 5 ]; then 635 break 636 fi 637 sleep 1 638 done 639 640 echo "create /dev/mem failed" 641 return 1 642} 643 644function show_usage(){ 645 echo "Usage: power-ctrl [sled1 | sled2 | sled3 | sled4 | sled5 | sled6] [$VALID_SLED_ACTIONS]" 646 echo " power-ctrl chassis-cycle" 647} 648 649 650if [ $# -eq 1 ]; then 651 if [ "$1" = "chassis-cycle" ];then 652 echo "chassis cycle...." 653 i2cset -y -f 12 0x11 0xd9 c 654 exit 0 655 else 656 echo "Invalid argument: [ $1 ]" 657 show_usage 658 exit 1; 659 fi 660fi 661 662if [ $# -gt 2 ]; then 663 echo "Too many arguments" 664 show_usage 665 exit 1; 666fi 667 668if [[ "$1" =~ ^(sled[1-6]{1})$ ]]; then 669 SLED=$1 670 ACTION=$2 671 SLED_NUM=${SLED:4} 672else 673 echo "invalid sled name: ${1}" 674 show_usage 675 exit 1; 676fi 677 678#Check if sled is present 679if ! is_sled_present "${SLED_NUM}"; then 680 echo "${SLED} is not present!" 681 exit 1 682elif ! is_valid_sled_action "$ACTION"; then 683 echo "Unknown action: $ACTION" 684 show_usage 685 exit 1 686fi 687 688if [ "$ACTION" = "$ACTION_AC_ON" ]; then 689 if [ "$(get_ac_status "$SLED_NUM")" = "$HOST_AC_OFF" ]; then 690 do_action_ac_on "$SLED_NUM" 691 fi 692elif [ "$ACTION" = "$ACTION_AC_OFF" ]; then 693 if [ "$(get_ac_status "$SLED_NUM")" != "$HOST_AC_OFF" ]; then 694 do_action_ac_off "$SLED_NUM" 695 fi 696elif [ "$ACTION" = "$ACTION_STATUS" ];then 697 HOST_CURR_STATUS=$(get_host_status "$SLED_NUM") 698 echo "$HOST_CURR_STATUS" 699else 700 HOST_CURR_STATUS=$(get_host_status "$SLED_NUM") 701 702 if [ "$ACTION" = "$ACTION_BOOT_MODE" ]; then 703 BOOT_MODE=$(get_host_bootmode "$SLED_NUM") 704 case "$BOOT_MODE" in 705 "$BOOT_MODE_REGULAR") 706 echo "Boot mode: on (regular)" 707 ACTION="$ACTION_ON" 708 ;; 709 "$BOOT_MODE_SAFE") 710 echo "Boot mode: recovery (safe)" 711 ACTION="$ACTION_RECOVERY" 712 ;; 713 "$BOOT_MODE_SETUP") 714 echo "Boot mode: dfu (setup)" 715 ACTION="$ACTION_DFU" 716 ;; 717 *) 718 echo "Boot mode: unknow" 719 ;; 720 esac 721 fi 722 723 case $HOST_CURR_STATUS in 724 "$HOST_AC_OFF") 725 host_state_ac_off_action_handler "$SLED_NUM" "$ACTION" 726 ;; 727 "$HOST_AC_ON") 728 host_state_ac_on_action_handler "$SLED_NUM" "$ACTION" 729 ;; 730 "$HOST_ST_OFF") 731 host_state_off_action_handler "$SLED_NUM" "$ACTION" 732 ;; 733 "$HOST_ST_ON") 734 host_state_on_action_handler "$SLED_NUM" "$ACTION" 735 ;; 736 "$HOST_ST_SLEEP") 737 host_state_sleep_action_handler "$SLED_NUM" "$ACTION" 738 ;; 739 "$HOST_ST_DFU") 740 host_state_dfu_action_handler "$SLED_NUM" "$ACTION" 741 ;; 742 "$HOST_ST_RECOVERY") 743 host_state_recovery_action_handler "$SLED_NUM" "$ACTION" 744 ;; 745 esac 746fi 747