diff --git a/bmc.sh b/bmc.sh index 3fe099d..d2ea9a4 100755 --- a/bmc.sh +++ b/bmc.sh @@ -1,5 +1,23 @@ #!/bin/bash +# +# bmc.sh - BMC command shell +# +# This program works as the main user shell for the RPi BMC. It provides a +# command-line interface for interfacing with the running bmcd daemon +# program as well as a few distinct functions such as a serial console, as +# well as managing the BMC itself (e.g. BMC hostname, IP address, or host +# system name. It is designed to be started automatically on login to the +# BMC as the 'bmc' user, e.g. with the following passwd file entry: +# bmc:x:2000:2000:BMC:/home/dir:/path/to/bmc.sh +# +# Has dependencies on the 'bmcd' and 'screen' utilities. +# +# Part of the RPiBMC project - (c)2017 Joshua Boniface +# This software is licenced under the terms of the GNU GPL version 3. For +# details please see LICENSE +# + stty eof undef stty intr undef @@ -79,7 +97,10 @@ readpower() { fi } +# Read the power state readpower + +# Print our login splash echo echo -e "--------------------" echo -e "| Raspberry Pi BMC |" @@ -90,102 +111,108 @@ echo -e "Host state: ${powerstate}" echo help echo + +# Main loop while true; do -stty eof undef -stty intr undef -echo -en "\e[1m\e[34m[$(hostname)]>\e[0m " -read input -case ${input} in - 'state') - readpower - echo -e "Host state: ${powerstate}" - echo - ;; - 'console') - echo "Starting console..." - # Connect to screen, or start it - sudo screen -r serialconsole &>/dev/null || sudo screen -S serialconsole /dev/ttyUSB0 115200 - # If the user killed screen, restart it - just in case - pgrep screen &>/dev/null || sudo screen -S serialconsole /dev/ttyUSB0 115200 - echo - ;; - 'power') - powersw_press - readpower - echo -e "Host state: ${powerstate}" - echo - ;; - 'reset') - resetsw_press - echo - ;; - 'kill') - powersw_hold - readpower - echo -e "Host state: ${powerstate}" - echo - ;; - 'locate') - locate_on - echo - ;; - 'unlocate') - locate_off - echo - ;; - 'help') - help - echo - ;; - 'bmc') - bmcinfo - echo - ;; - 'hostname') - echo -n "Enter new hostname: " - read newhostname - sethostname ${newhostname} - echo - ;; - 'host') - echo -n "Enter new host system name: " - read newhost - sethost ${newhost} - echo -n "Update BMC hostname to '${newhost}-bmc'? (y/N) " - read updatehostnameyn - if [[ "${updatehostnameyn}" =~ "y" ]]; then - sethostname "${newhost}-bmc" - fi - ;; - 'password') - echo -n "Enter new BMC password: " - read -s password_1 - echo - echo -n "Reenter new BMC password: " - read -s password_2 - echo - if [ "${password_1}" == "${password_2}" ]; then - setpassword "${password_1}" - else - echo "Passwords to not match!" - fi - echo - ;; - 'shell') - stty sane - /bin/bash - help - echo - ;; - 'exit'|'logout') - exit 0 - ;; - '') - continue - ;; - *) - echo "Invalid command." - echo - ;; -esac + stty eof undef + stty intr undef + + # Prompt + echo -en "\e[1m\e[34m[$(hostname)]>\e[0m " + # Read input + read input + # Process input + case ${input} in + 'state') + readpower + echo -e "Host state: ${powerstate}" + echo + ;; + 'console') + echo "Starting console..." + # Connect to screen, or start it + sudo screen -r serialconsole &>/dev/null || sudo screen -S serialconsole /dev/ttyUSB0 115200 + # If the user killed screen, restart it - just in case + pgrep screen &>/dev/null || sudo screen -S serialconsole /dev/ttyUSB0 115200 + echo + ;; + 'power') + powersw_press + readpower + echo -e "Host state: ${powerstate}" + echo + ;; + 'reset') + resetsw_press + echo + ;; + 'kill') + powersw_hold + readpower + echo -e "Host state: ${powerstate}" + echo + ;; + 'locate') + locate_on + echo + ;; + 'unlocate') + locate_off + echo + ;; + 'help') + help + echo + ;; + 'bmc') + bmcinfo + echo + ;; + 'hostname') + echo -n "Enter new hostname: " + read newhostname + sethostname ${newhostname} + echo + ;; + 'host') + echo -n "Enter new host system name: " + read newhost + sethost ${newhost} + echo -n "Update BMC hostname to '${newhost}-bmc'? (y/N) " + read updatehostnameyn + if [[ "${updatehostnameyn}" =~ "y" ]]; then + sethostname "${newhost}-bmc" + fi + ;; + 'password') + echo -n "Enter new BMC password: " + read -s password_1 + echo + echo -n "Reenter new BMC password: " + read -s password_2 + echo + if [ "${password_1}" == "${password_2}" ]; then + setpassword "${password_1}" + else + echo "Passwords to not match!" + fi + echo + ;; + 'shell') + stty sane + /bin/bash + help + echo + ;; + 'exit'|'logout') + exit 0 + ;; + '') + continue + ;; + *) + echo "Invalid command." + echo + ;; + esac done diff --git a/bmcd b/bmcd index 0ee710a..b06f940 100755 --- a/bmcd +++ b/bmcd @@ -1,27 +1,47 @@ #!/usr/bin/env python +# +# bmcd - BMC Daemon program +# +# This program works as a background daemon for the RPi BMC. It provides +# functionality to interface with the GPIOs in an asynchronous way via two +# pipes, one read-only and one write-only from the outside perspective. The read +# pipe provides the current system power status while the write pipe listens +# for commands. +# +# Part of the RPiBMC project - (c)2017 Joshua Boniface +# This software is licenced under the terms of the GNU GPL version 3. For +# details please see LICENSE +# + import socket, os, time, struct from threading import Thread, Event from daemon import runner import RPi.GPIO as GPIO +# These are GPIOs 1-4 gpio_rsw = 17 gpio_psw = 18 gpio_state = 27 gpio_pled = 22 +# The pipes and PID file (sorry I manage this here...) bmcd_state = '/run/bmcd/bmcd.state' bmcd_cmd = '/run/bmcd/bmcd.cmd' pidfile = '/run/bmcd/bmcd.pid' +# Event for LED flash (i.e. locator) is_pled_flashing = Event() +# Turn the power LED on def powerled_on(): GPIO.output(gpio_pled, 1) +# Turn the power LED off def powerled_off(): GPIO.output(gpio_pled, 0) +# Flash the power LED def powerled_flash(is_pled_flashing): while is_pled_flashing.isSet(): GPIO.output(gpio_pled, 1) @@ -31,29 +51,35 @@ def powerled_flash(is_pled_flashing): is_pled_flashing.clear() return +# Press the power button def powersw_press(): GPIO.output(gpio_psw, 1) time.sleep(0.5) GPIO.output(gpio_psw, 0) +# Hold the power button (8 seconds) def powersw_hold(): GPIO.output(gpio_psw, 1) time.sleep(8) GPIO.output(gpio_psw, 0) +# Press the reset button def resetsw_press(): GPIO.output(gpio_rsw, 1) time.sleep(0.5) GPIO.output(gpio_rsw, 0) +# Turn on the locator (subthread) def locate_on(): is_pled_flashing.set() t = Thread(name='non-block', target=powerled_flash, args=(is_pled_flashing,)) t.start() +# Turn off the locator def locate_off(): is_pled_flashing.clear() +# Read a command from the pipe def readcmd(): fcmd = open(bmcd_cmd, 'r+', 0) while True: @@ -63,6 +89,7 @@ def readcmd(): except: pass +# Main loop def writestate(is_pled_flashing): while True: state_now = GPIO.input(gpio_state) @@ -77,7 +104,7 @@ def writestate(is_pled_flashing): time.sleep(1) - +# Main app definiton - sets default states and runs main loop class App(): def __init__(self): self.stdin_path = '/dev/null' @@ -106,7 +133,7 @@ class App(): while True: pass +# App definition - start it up app = App() daemon_runner = runner.DaemonRunner(app) daemon_runner.do_action() - diff --git a/rc.local b/rc.local index 2b2d849..89b64d6 100755 --- a/rc.local +++ b/rc.local @@ -1,17 +1,48 @@ #!/bin/bash -e # -# rc.local for RPiBMC +# rc.local - BMC startup rc.local file +# +# This file replaces the default rc.local (or can be appended to it) to +# ensure the BMC daemon and serial console sesson start at boot and have +# the proper permissions for bmc.sh to work as expected. It also writes +# some useful debug information to /var/log/rc.local.log should later boot +# analysis be needed. +# +# Has dependencies on the 'bmcd' and 'screen' utilities. +# +# Part of the RPiBMC project - (c)2017 Joshua Boniface +# This software is licenced under the terms of the GNU GPL version 3. For +# details please see LICENSE +# + +# Write all output to rc.local.log file exec 1>>/var/log/rc.local.log exec 2>>/var/log/rc.local.log + +# Write when we booted echo "#" echo "# Boot at $(date) " echo "#" + +# Turn on verbose BASH mode for logging visibility set -x -/usr/bin/screen -dmS serialconsole /dev/ttyUSB0 115200 + +# Start the screen session to /dev/ttyAMA0 (115200 baud) +/usr/bin/screen -dmS serialconsole /dev/ttyAMA0 115200 + +# Check if the temporary bmcd directory exists, or create it test -d /run/bmcd || mkdir /run/bmcd + +# Start the bmcd daemon /home/bmc/rpibmc/bmcd start + +# Wait 5 seconds for the daemon startup routines sleep 5 + +# Change the temporary bmcd directory permissions to allow gpio group (only) access chgrp -R gpio /run/bmcd chmod -R 770 /run/bmcd + +# Turn off verbose BASH mode and exit 0 (as per rc.local requirements) set +x exit 0