diff --git a/sw/.gitignore b/sw/.gitignore index 6f30340..5a28233 100644 --- a/sw/.gitignore +++ b/sw/.gitignore @@ -1,5 +1,6 @@ devicetree/devicetree.dtb -buildroot_overlay/opt/ +buildroot_overlay/opt/puzzlefw/bin/puzzlecmd +buildroot_overlay/opt/puzzlefw/driver/ downloads/ buildroot-2023.02.8/ u-boot/ diff --git a/sw/buildroot_overlay/opt/puzzlefw/bin/puzzle-ipcfg b/sw/buildroot_overlay/opt/puzzlefw/bin/puzzle-ipcfg new file mode 100755 index 0000000..48083ea --- /dev/null +++ b/sw/buildroot_overlay/opt/puzzlefw/bin/puzzle-ipcfg @@ -0,0 +1,310 @@ +#!/bin/sh +# +# Manage IP address configuration. +# +# The IP address configuration exists in 3 places: +# +# - The persistent configuration is stored in network.conf on +# the configuration partition of the SD card. +# This configuration is activated on boot. +# +# The syntax of this file is as follows: +# +# MODE=dhcp / MODE=static +# IPADDR=172.16.3.4 +# NETMASK=255.255.0.0 +# GATEWAY=172.16.0.1 +# +# - The active configuration, which determines the actual IP address, +# is stored in /var/lib/puzzlefw/cfg/network_active.conf in +# the RAM filesystem. It has the same format as described above. +# +# The same information is also present in /etc/network/interfaces. +# + +. /opt/puzzlefw/lib/functions.sh + +# Load the persistent or active configuration. +# $1 = file name to read +load_network_config() { + + if [ ! -f ${CONFIG_DIR}/${1} ]; then + echo "ERROR: File not found ${CONFIG_DIR}/${1}" >&2 + exit 1 + fi + + . ${CONFIG_DIR}/${1} +} + +# Write configuration to file. +# $1 = file name to write +write_network_config() { + + mkdir -p ${CONFIG_DIR} + + cat >${CONFIG_DIR}/${1} </etc/network/interfaces.new <&2 + exit 1 + fi + done +} + +# Check that parameter is a valid IPv4 netmask. +check_netmask() { + IFS="." read a b c d <&2 + exit 1 + fi + if [ "$i" != "255" ]; then + netmask_force_zero=1 + netmask_ok=0 + for k in 254 252 248 240 224 192 128 0 ; do + if [ "$i" = "$k" ]; then + netmask_ok=1 + fi + done + if [ "$netmask_ok" != "1" ]; then + echo "ERROR: Invalid netmask '$1'" >&2 + exit 1 + fi + fi + done +} + +# Parse IP address options. +parse_options() { + + while [ -n "$1" ]; do + + case "$1" in + + --mode) + if [ "$2" != "dhcp" -a "$2" != "static" ]; then + echo "ERROR: Unknown mode '$2'" >&2 + exit 1 + fi + MODE="$2" + ;; + + --ipaddr) + check_ipaddr "$2" + IPADDR="$2" + ;; + + --netmask) + check_netmask "$2" + NETMASK="$2" + ;; + + --gateway) + [ -z "$2" ] || check_ipaddr "$2" + GATEWAY="$2" + ;; + + *) + echo "ERROR: Unknown option '$1'" >&2 + exit 1 + esac + + shift 2 + done + + if [ -z "$MODE" ]; then + echo "ERROR: Missing mode" >&2 + exit 1 + fi + + if [ "$MODE" = "static" ]; then + if [ -z "$IPADDR" ]; then + echo "ERROR: Missing IP address" >&2 + exit 1 + fi + if [ -z "$NETMASK" ]; then + echo "ERROR: Missing netmask" >&2 + exit 1 + fi + else + IPADDR="" + NETMASK="" + GATEWAY="" + fi +} + +# Change active IP address configuration. +ipcfg_config() { + + # Lock to avoid conflicting changes. + lock_config || exit 1 + + echo "Changing active IP address configuration ..." + + write_network_config network_active.conf.new + mv ${CONFIG_DIR}/network_active.conf.new ${CONFIG_DIR}/network_active.conf + + echo "Shutting down eth0 ..." + /sbin/ifdown eth0 + sleep 2 + + write_network_interfaces + + echo "Starting eth0 ..." + /sbin/ifup eth0 || exit 1 +} + +# Change the persistent IP address configuration on the SD card. +ipcfg_save() { + + # Lock to avoid conflicting changes. + lock_config || exit 1 + + echo "Changing saved IP address configuration ..." + + write_network_config network.conf.new || exit 1 + sync_config network.conf || exit 1 +} + +case "$1" in + init) + ipcfg_init + ;; + show) + ipcfg_show + ;; + config) + shift + parse_options "$@" + ipcfg_config + ;; + save) + shift + parse_options "$@" + ipcfg_save + ;; + *) + cat <>${CONFIG_DIR}/lockfile + + # Get exclusive lock on the file. + if ! flock -n 3 ; then + echo "ERROR: Configuration locked" >&2 + return 1 + fi +} + +# Read configuration files from the SD card. +# This is only used during boot. +read_config() { + + # Mount config filesystem read-only. + mkdir -p $CONFIG_MOUNTPOINT + mount -t ext4 -r -o noatime,data=journal /dev/${CONFIG_PARTITION} $CONFIG_MOUNTPOINT || return 1 + + # Copy config files to RAM filesystem. + cp -a ${CONFIG_MOUNTPOINT}/*.conf $CONFIG_DIR + + umount $CONFIG_MOUNTPOINT +} + +# Write changed configuration files to the SD card. +# Parameters: names of config files to synchronize +sync_config() { + + # Mount config filesystem. + mkdir -p $CONFIG_MOUNTPOINT + mount -t ext4 -o noatime,data=journal /dev/${CONFIG_PARTITION} $CONFIG_MOUNTPOINT || return 1 + + for fname in "$@" ; do + + # Copy new version of file to SD card. + cp ${CONFIG_DIR}/${fname}.new $CONFIG_MOUNTPOINT + + # Atomically replace the old file on the SD card. + mv ${CONFIG_MOUNTPOINT}/${fname}.new ${CONFIG_MOUNTPOINT}/${fname} + + # Replace the old file in te RAM filesystem. + mv ${CONFIG_DIR}/${fname}.new ${CONFIG_DIR}/${fname} + done + + umount $CONFIG_MOUNTPOINT + sync +} +