#!/bin/bash # Part of kalipi-config https://github.com/Re4son/RPi-Tweaks/tree/master/kalipi-config # Based on raspi-config https://github.com/RPi-Distro/raspi-config # # re4son [at] re4son-kernel.com # # See LICENSE file for copyright and license details INTERACTIVE=True ASK_TO_REBOOT=0 BLACKLIST=/etc/modprobe.d/kalipi-blacklist.conf CONFIG=/boot/config.txt PROG_NAME="$0" ARGS="$@" VERSION="4.19-1.1.0" if [[ ! "$LD_LIBRARY_PATH" =~ (^|:)"/opt/vc/lib"(|/)(:|$) ]]; then export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/vc/lib/; fi info() { system="$1" group="${system}" shift FG="1;32m" BG="40m" echo "[\033[${FG}\033[${BG}${system}\033[0m] $*" } is_pi () { ARCH=$(dpkg --print-architecture) if [ "$ARCH" = "armhf" ] || [ "$ARCH" = "armel" ]; then return 0 else return 1 fi } if is_pi ; then CMDLINE=/boot/cmdline.txt else CMDLINE=/proc/cmdline fi is_pione() { if grep -q "^Revision\s*:\s*00[0-9a-fA-F][0-9a-fA-F]$" /proc/cpuinfo; then return 0 elif grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]0[0-36][0-9a-fA-F]$" /proc/cpuinfo ; then return 0 else return 1 fi } is_pitwo() { grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]04[0-9a-fA-F]$" /proc/cpuinfo return $? } is_pizero() { grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]0[9cC][0-9a-fA-F]$" /proc/cpuinfo return $? } set_sudo_user() { if [ -z "$SUDO_USER" ]; then SUDO_USER=root fi return 0 } get_pi_type() { if is_pione; then echo 1 elif is_pitwo; then echo 2 else echo 0 fi } is_live() { grep -q "boot=live" $CMDLINE return $? } is_ssh() { if pstree -p | egrep --quiet --extended-regexp ".*sshd.*\($$\)"; then return 0 else return 1 fi } print_version() { echo "kalipi-config $VERSION" exit 0 } check_bin(){ BIN_PATH=$(which $1) if [ "" = "$BIN_PATH" ]; then echo 0 else echo 1 fi } check_pkg(){ PKG_STATUS=$(dpkg-query -W --showformat='${Status}\n' $1|grep "install ok installed") if [ "" = "$PKG_STATUS" ]; then echo 0 else echo 1 fi } calc_wt_size() { # NOTE: it's tempting to redirect stderr to /dev/null, so supress error # output from tput. However in this case, tput detects neither stdout or # stderr is a tty and so only gives default 80, 24 values WT_HEIGHT=17 WT_WIDTH=$(tput cols) if [ -z "$WT_WIDTH" ] || [ "$WT_WIDTH" -lt 100 ]; then WT_WIDTH=90 elif [ "$WT_WIDTH" -gt 178 ]; then WT_WIDTH=120 else WT_WIDTH=$((WT_WIDTH-10)) fi WT_MENU_HEIGHT=$(($WT_HEIGHT-7)) } do_about() { whiptail --msgbox "\ kalipi-config version $VERSION This tool provides a straight-forward way of doing initial configuration of the Kali-Pi. Although it can be run at any time, some of the options may have difficulties if you have heavily customised your installation.\ " 20 70 1 } function do_kalipi_tft_config() { BIN_PATH=$(which kalipi-tft-config) if [ "" = "$BIN_PATH" ]; then whiptail --msgbox "\ Error: The tool "kalipi-tft-config" cannot be found on this system. It can be installed from this site: https://github.com/Re4son/RPi-Tweaks/tree/master/kalipi-tft-config " 20 70 1 else exec $BIN_PATH fi } get_partvars () { ROOT_PART_DEV=$(findmnt / -o source -n) ROOT_PART_NAME=$(echo "$ROOT_PART_DEV" | cut -d "/" -f 3) ROOT_DEV_NAME=$(echo /sys/block/*/"${ROOT_PART_NAME}" | cut -d "/" -f 4) ROOT_DEV="/dev/${ROOT_DEV_NAME}" ROOT_PART_NUM=$(cat "/sys/block/${ROOT_DEV_NAME}/${ROOT_PART_NAME}/partition") BOOT_PART_DEV=$(findmnt /boot -o source -n) BOOT_PART_NAME=$(echo "$BOOT_PART_DEV" | cut -d "/" -f 3) BOOT_DEV_NAME=$(echo /sys/block/*/"${BOOT_PART_NAME}" | cut -d "/" -f 4) BOOT_PART_NUM=$(cat "/sys/block/${BOOT_DEV_NAME}/${BOOT_PART_NAME}/partition") OLD_DISKID=$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p') ROOT_DEV_SIZE=$(cat "/sys/block/${ROOT_DEV_NAME}/size") TARGET_END=$((ROOT_DEV_SIZE - 1)) PARTITION_TABLE=$(parted -m "$ROOT_DEV" unit s print | tr -d 's') LAST_PART_NUM=$(echo "$PARTITION_TABLE" | tail -n 1 | cut -d ":" -f 1) ROOT_PART_LINE=$(echo "$PARTITION_TABLE" | grep -e "^${ROOT_PART_NUM}:") ROOT_PART_START=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 2) ROOT_PART_END=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 3) } check_partvars () { if [ "$BOOT_DEV_NAME" != "$ROOT_DEV_NAME" ]; then FAIL_REASON="Boot and root partitions are on different devices" return 1 fi if [ "$ROOT_PART_NUM" -ne "$LAST_PART_NUM" ]; then FAIL_REASON="Root partition should be last partition" return 1 fi if [ "$ROOT_PART_END" -gt "$TARGET_END" ]; then FAIL_REASON="Root partition runs past the end of device" return 1 fi if [ ! -b "$ROOT_DEV" ] || [ ! -b "$ROOT_PART_DEV" ] || [ ! -b "$BOOT_PART_DEV" ] ; then FAIL_REASON="Could not determine partitions" return 1 fi } fix_partuuid() { DISKID="$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p')" sed -i "s/${OLD_DISKID}/${DISKID}/g" /etc/fstab sed -i "s/${OLD_DISKID}/${DISKID}/" /boot/cmdline.txt } do_expand_rootfs() { get_partvars if ! check_partvars; then whiptail --msgbox "Could not expand filesystem, please try manually.\n${FAIL_REASON}" 20 60 return 1 fi if ! parted -m "$ROOT_DEV" u s resizepart "$ROOT_PART_NUM" "$TARGET_END"; then whiptail --msgbox "Could not expand filesystem, please try manually.\nRoot partition resize failed" 20 60 return 1 fi partprobe "$ROOT_DEV" resize2fs $ROOT_PART_DEV fix_partuuid if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Root partition has been resized successfully." 20 60 2 fi } set_config_var() { lua - "$1" "$2" "$3" < "$3.bak" local key=assert(arg[1]) local value=assert(arg[2]) local fn=assert(arg[3]) local file=assert(io.open(fn)) local made_change=false for line in file:lines() do if line:match("^#?%s*"..key.."=.*$") then line=key.."="..value made_change=true end print(line) end if not made_change then print(key.."="..value) end EOF mv "$3.bak" "$3" } clear_config_var() { lua - "$1" "$2" < "$2.bak" local key=assert(arg[1]) local fn=assert(arg[2]) local file=assert(io.open(fn)) for line in file:lines() do if line:match("^%s*"..key.."=.*$") then line="#"..line end print(line) end EOF mv "$2.bak" "$2" } get_config_var() { lua - "$1" "$2" <&1 | grep current | cut -f2 -d, | cut -f3 -d' ') YVAL=$(xrandr 2>&1 | grep current | cut -f2 -d, | cut -f5 -d' ') if is_number $XVAL || is_number $YVAL ; then if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Could not read current screen dimensions - unable to enable pixel doubling" 20 60 1 fi return 1 fi NEWX=`expr $XVAL / 2` NEWY=`expr $YVAL / 2` set_config_var framebuffer_width $NEWX $CONFIG set_config_var framebuffer_height $NEWY $CONFIG set_config_var scaling_kernel 8 $CONFIG STATUS=enabled elif [ $RET -eq 1 ]; then clear_config_var framebuffer_width $CONFIG clear_config_var framebuffer_height $CONFIG clear_config_var scaling_kernel $CONFIG STATUS=disabled else return $RET fi else if [ -e /etc/profile.d/pd.sh ] ; then rm /etc/profile.d/pd.sh fi if [ $RET -eq 0 ] ; then DEV=$(xrandr | grep -w connected | cut -f1 -d' ') for item in $DEV do echo xrandr --output $item --scale 0.5x0.5 >> /etc/profile.d/pd.sh done STATUS=enabled elif [ $RET -eq 1 ]; then STATUS=disabled else return $RET fi fi if [ $RET -eq $CURRENT ]; then ASK_TO_REBOOT=1 fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Pixel doubling is $STATUS" 20 60 1 fi } do_change_pass() { AVAIL_USERS=$(awk -F'[/:]' '{if (($3 >= 1000 && $3 != 65534) || $3 == 0) print $1}' /etc/passwd) whiptail --msgbox "Users on this system (Tip: use copy and paste):\n\n$AVAIL_USERS" 20 90 USER=$(whiptail --inputbox "Please enter the username to change the poassword of\n(leave empty for $SUDO_USER):" 20 60 3>&1 1>&2 2>&3) if [ $? -ne 0 ]; then return 0 elif [ -z "$USER" ]; then USER=$SUDO_USER fi whiptail --msgbox "You will now be asked to enter a new password for user \"$USER\"" 20 60 1 passwd $USER && whiptail --msgbox "Password changed successfully" 20 60 1 } do_configure_keyboard() { printf "Reloading keymap. This may take a short while\n" if [ "$INTERACTIVE" = True ]; then dpkg-reconfigure keyboard-configuration else local KEYMAP="$1" sed -i /etc/default/keyboard -e "s/^XKBLAYOUT.*/XKBLAYOUT=\"$KEYMAP\"/" dpkg-reconfigure -f noninteractive keyboard-configuration fi invoke-rc.d keyboard-setup start setsid sh -c 'exec setupcon -k --force <> /dev/tty1 >&0 2>&1' udevadm trigger --subsystem-match=input --action=change return 0 } do_change_locale() { if [ "$INTERACTIVE" = True ]; then dpkg-reconfigure locales else local LOCALE="$1" if ! LOCALE_LINE="$(grep "^$LOCALE " /usr/share/i18n/SUPPORTED)"; then return 1 fi local ENCODING="$(echo $LOCALE_LINE | cut -f2 -d " ")" echo "$LOCALE $ENCODING" > /etc/locale.gen sed -i "s/^\s*LANG=\S*/LANG=$LOCALE/" /etc/default/locale dpkg-reconfigure -f noninteractive locales fi } do_change_timezone() { if [ "$INTERACTIVE" = True ]; then dpkg-reconfigure tzdata else local TIMEZONE="$1" if [ ! -f "/usr/share/zoneinfo/$TIMEZONE" ]; then return 1; fi rm /etc/localtime echo "$TIMEZONE" > /etc/timezone dpkg-reconfigure -f noninteractive tzdata fi } get_wifi_country() { grep country= /etc/wpa_supplicant/wpa_supplicant.conf | cut -d "=" -f 2 } do_wifi_country() { oIFS="$IFS" if [ "$INTERACTIVE" = True ]; then IFS="/" value=$(cat /usr/share/zoneinfo/iso3166.tab | tail -n +26 | tr '\t' '/' | tr '\n' '/') COUNTRY=$(whiptail --menu "Select the country in which the Pi is to be used" 20 60 10 ${value} 3>&1 1>&2 2>&3) else COUNTRY=$1 true fi if [ $? -eq 0 ];then if [ -e /etc/wpa_supplicant/wpa_supplicant.conf ]; then if grep -q "^country=" /etc/wpa_supplicant/wpa_supplicant.conf ; then sed -i --follow-symlinks "s/^country=.*/country=$COUNTRY/g" /etc/wpa_supplicant/wpa_supplicant.conf else sed -i --follow-symlinks "1i country=$COUNTRY" /etc/wpa_supplicant/wpa_supplicant.conf fi else echo "country=$COUNTRY" > /etc/wpa_supplicant/wpa_supplicant.conf fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Wi-fi country set to $COUNTRY" 20 60 1 fi ASK_TO_REBOOT=1 fi IFS=$oIFS } get_hostname() { cat /etc/hostname | tr -d " \t\n\r" } do_hostname() { if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "\ Please note: RFCs mandate that a hostname's labels \ may contain only the ASCII letters 'a' through 'z' (case-insensitive), the digits '0' through '9', and the hyphen. Hostname labels cannot begin or end with a hyphen. No other symbols, punctuation characters, or blank spaces are permitted.\ " 20 70 1 fi CURRENT_HOSTNAME=`cat /etc/hostname | tr -d " \t\n\r"` if [ "$INTERACTIVE" = True ]; then NEW_HOSTNAME=$(whiptail --inputbox "Please enter a hostname" 20 60 "$CURRENT_HOSTNAME" 3>&1 1>&2 2>&3) else NEW_HOSTNAME=$1 true fi if [ $? -eq 0 ]; then echo $NEW_HOSTNAME > /etc/hostname sed -i "s/127.0.1.1.*$CURRENT_HOSTNAME/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts ASK_TO_REBOOT=1 fi } do_memory_split() { # Memory Split if [ -e /boot/start_cd.elf ]; then # New-style memory split setting ## get current memory split from /boot/config.txt arm=$(vcgencmd get_mem arm | cut -d '=' -f 2 | cut -d 'M' -f 1) gpu=$(vcgencmd get_mem gpu | cut -d '=' -f 2 | cut -d 'M' -f 1) tot=$(($arm+$gpu)) if [ $tot -gt 512 ]; then CUR_GPU_MEM=$(get_config_var gpu_mem_1024 $CONFIG) elif [ $tot -gt 256 ]; then CUR_GPU_MEM=$(get_config_var gpu_mem_512 $CONFIG) else CUR_GPU_MEM=$(get_config_var gpu_mem_256 $CONFIG) fi if [ -z "$CUR_GPU_MEM" ] || [ $CUR_GPU_MEM = "0" ]; then CUR_GPU_MEM=$(get_config_var gpu_mem $CONFIG) fi [ -z "$CUR_GPU_MEM" ] || [ $CUR_GPU_MEM = "0" ] && CUR_GPU_MEM=64 ## ask users what gpu_mem they want if [ "$INTERACTIVE" = True ]; then NEW_GPU_MEM=$(whiptail --inputbox "How much memory (MB) should the GPU have? e.g. 16/32/64/128/256" \ 20 70 -- "$CUR_GPU_MEM" 3>&1 1>&2 2>&3) else NEW_GPU_MEM=$1 true fi if [ $? -eq 0 ]; then if [ $(get_config_var gpu_mem_1024 $CONFIG) != "0" ] || [ $(get_config_var gpu_mem_512 $CONFIG) != "0" ] || [ $(get_config_var gpu_mem_256 $CONFIG) != "0" ]; then if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Device-specific memory settings were found. These have been cleared." 20 60 2 fi clear_config_var gpu_mem_1024 $CONFIG clear_config_var gpu_mem_512 $CONFIG clear_config_var gpu_mem_256 $CONFIG fi set_config_var gpu_mem "$NEW_GPU_MEM" $CONFIG ASK_TO_REBOOT=1 fi else # Old firmware so do start.elf renaming get_current_memory_split MEMSPLIT=$(whiptail --menu "Set memory split.\n$MEMSPLIT_DESCRIPTION" 20 60 10 \ "240" "240MiB for ARM, 16MiB for VideoCore" \ "224" "224MiB for ARM, 32MiB for VideoCore" \ "192" "192MiB for ARM, 64MiB for VideoCore" \ "128" "128MiB for ARM, 128MiB for VideoCore" \ 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then set_memory_split ${MEMSPLIT} ASK_TO_REBOOT=1 fi fi } get_current_memory_split() { AVAILABLE_SPLITS="128 192 224 240" MEMSPLIT_DESCRIPTION="" for SPLIT in $AVAILABLE_SPLITS;do if [ -e /boot/arm${SPLIT}_start.elf ] && cmp /boot/arm${SPLIT}_start.elf /boot/start.elf >/dev/null 2>&1;then CURRENT_MEMSPLIT=$SPLIT MEMSPLIT_DESCRIPTION="Current: ${CURRENT_MEMSPLIT}MiB for ARM, $((256 - $CURRENT_MEMSPLIT))MiB for VideoCore" break fi done } set_memory_split() { cp -a /boot/arm${1}_start.elf /boot/start.elf sync } do_overclock() { if ! is_pione && ! is_pitwo; then whiptail --msgbox "This Pi cannot be overclocked." 20 60 2 return 1 fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "\ Be aware that overclocking may reduce the lifetime of your Raspberry Pi. If overclocking at a certain level causes system instability, try a more modest overclock. Hold down shift during boot to temporarily disable overclock. See http://elinux.org/RPi_Overclocking for more information.\ " 20 70 1 if is_pione; then OVERCLOCK=$(whiptail --menu "Choose overclock preset" 20 60 10 \ "None" "700MHz ARM, 250MHz core, 400MHz SDRAM, 0 overvolt" \ "Modest" "800MHz ARM, 250MHz core, 400MHz SDRAM, 0 overvolt" \ "Medium" "900MHz ARM, 250MHz core, 450MHz SDRAM, 2 overvolt" \ "High" "950MHz ARM, 250MHz core, 450MHz SDRAM, 6 overvolt" \ "Turbo" "1000MHz ARM, 500MHz core, 600MHz SDRAM, 6 overvolt" \ 3>&1 1>&2 2>&3) elif is_pitwo; then OVERCLOCK=$(whiptail --menu "Choose overclock preset" 20 60 10 \ "None" "900MHz ARM, 250MHz core, 450MHz SDRAM, 0 overvolt" \ "High" "1000MHz ARM, 500MHz core, 500MHz SDRAM, 2 overvolt" \ 3>&1 1>&2 2>&3) fi else OVERCLOCK=$1 true fi if [ $? -eq 0 ]; then case "$OVERCLOCK" in None) clear_overclock ;; Modest) set_overclock Modest 800 250 400 0 ;; Medium) set_overclock Medium 900 250 450 2 ;; High) if is_pione; then set_overclock High 950 250 450 6 else set_overclock High 1000 500 500 2 fi ;; Turbo) set_overclock Turbo 1000 500 600 6 ;; *) whiptail --msgbox "Program error, unrecognised overclock preset" 20 60 2 return 1 ;; esac ASK_TO_REBOOT=1 fi } set_overclock() { set_config_var arm_freq $2 $CONFIG && set_config_var core_freq $3 $CONFIG && set_config_var sdram_freq $4 $CONFIG && set_config_var over_voltage $5 $CONFIG && if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Set overclock to preset '$1'" 20 60 2 fi } clear_overclock () { clear_config_var arm_freq $CONFIG && clear_config_var core_freq $CONFIG && clear_config_var sdram_freq $CONFIG && clear_config_var over_voltage $CONFIG && if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Set overclock to preset 'None'" 20 60 2 fi } get_ssh() { if service ssh status | grep -q inactive; then echo 1 else echo 0 fi } do_ssh() { if [ -e /var/log/regen_ssh_keys.log ] && ! grep -q "^finished" /var/log/regen_ssh_keys.log; then whiptail --msgbox "Initial ssh key generation still running. Please wait and try again." 20 60 2 return 1 fi DEFAULT=--defaultno if [ $(get_ssh) -eq 0 ]; then DEFAULT= fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the SSH server to be enabled?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq 0 ]; then systemctl enable ssh && systemctl start ssh && STATUS=enabled elif [ $RET -eq 1 ]; then systemctl disable ssh && systemctl stop ssh && STATUS=disabled else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The SSH server is $STATUS" 20 60 1 fi } get_vnc() { if systemctl status vncserver-x11-serviced.service | grep -q inactive; then echo 1 else echo 0 fi } do_vnc() { DEFAULT=--defaultno if [ $(get_vnc) -eq 0 ]; then DEFAULT= fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the VNC Server to be enabled?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq 0 ]; then if [ ! -d /usr/share/doc/realvnc-vnc-server ] ; then apt-get install realvnc-vnc-server fi systemctl enable vncserver-x11-serviced.service && systemctl start vncserver-x11-serviced.service && STATUS=enabled elif [ $RET -eq 1 ]; then systemctl disable vncserver-x11-serviced.service && systemctl stop vncserver-x11-serviced.service && STATUS=disabled else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The VNC Server is $STATUS" 20 60 1 fi } get_spi() { if grep -q -E "^(device_tree_param|dtparam)=([^,]*,)*spi(=(on|true|yes|1))?(,.*)?$" $CONFIG; then echo 0 else echo 1 fi } do_spi() { DEFAULT=--defaultno if [ $(get_spi) -eq 0 ]; then DEFAULT= fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the SPI interface to be enabled?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq 0 ]; then SETTING=on STATUS=enabled elif [ $RET -eq 1 ]; then SETTING=off STATUS=disabled else return $RET fi set_config_var dtparam=spi $SETTING $CONFIG && if ! [ -e $BLACKLIST ]; then touch $BLACKLIST fi sed $BLACKLIST -i -e "s/^\(blacklist[[:space:]]*spi[-_]bcm2708\)/#\1/" dtparam spi=$SETTING if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The SPI interface is $STATUS" 20 60 1 fi } get_i2c() { if grep -q -E "^(device_tree_param|dtparam)=([^,]*,)*i2c(_arm)?(=(on|true|yes|1))?(,.*)?$" $CONFIG; then echo 0 else echo 1 fi } do_i2c() { DEFAULT=--defaultno if [ $(get_i2c) -eq 0 ]; then DEFAULT= fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the ARM I2C interface to be enabled?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq 0 ]; then SETTING=on STATUS=enabled elif [ $RET -eq 1 ]; then SETTING=off STATUS=disabled else return $RET fi set_config_var dtparam=i2c_arm $SETTING $CONFIG && if ! [ -e $BLACKLIST ]; then touch $BLACKLIST fi sed $BLACKLIST -i -e "s/^\(blacklist[[:space:]]*i2c[-_]bcm2708\)/#\1/" sed /etc/modules -i -e "s/^#[[:space:]]*\(i2c[-_]dev\)/\1/" if ! grep -q "^i2c[-_]dev" /etc/modules; then printf "i2c-dev\n" >> /etc/modules fi dtparam i2c_arm=$SETTING modprobe i2c-dev if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The ARM I2C interface is $STATUS" 20 60 1 fi } get_serial() { if grep -q -E "console=(serial0|ttyAMA0|ttyS0)" $CMDLINE ; then echo 0 else echo 1 fi } get_serial_hw() { if grep -q -E "^enable_uart=1" $CONFIG ; then echo 0 elif grep -q -E "^enable_uart=0" $CONFIG ; then echo 1 elif [ -e /dev/serial0 ] ; then echo 0 else echo 1 fi } do_serial() { DEFAULTS=--defaultno DEFAULTH=--defaultno CURRENTS=0 CURRENTH=0 if [ $(get_serial) -eq 0 ]; then DEFAULTS= CURRENTS=1 fi if [ $(get_serial_hw) -eq 0 ]; then DEFAULTH= CURRENTH=1 fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like a login shell to be accessible over serial?" $DEFAULTS 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq $CURRENTS ]; then ASK_TO_REBOOT=1 fi if [ $RET -eq 0 ]; then if grep -q "console=ttyAMA0" $CMDLINE ; then if [ -e /proc/device-tree/aliases/serial0 ]; then sed -i $CMDLINE -e "s/console=ttyAMA0/console=serial0/" fi elif ! grep -q "console=ttyAMA0" $CMDLINE && ! grep -q "console=serial0" $CMDLINE ; then if [ -e /proc/device-tree/aliases/serial0 ]; then sed -i $CMDLINE -e "s/root=/console=serial0,115200 root=/" else sed -i $CMDLINE -e "s/root=/console=ttyAMA0,115200 root=/" fi fi set_config_var enable_uart 1 $CONFIG SSTATUS=enabled HSTATUS=enabled elif [ $RET -eq 1 ]; then sed -i $CMDLINE -e "s/console=ttyAMA0,[0-9]\+ //" sed -i $CMDLINE -e "s/console=serial0,[0-9]\+ //" SSTATUS=disabled if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the serial port hardware to be enabled?" $DEFAULTH 20 60 2 RET=$? else RET=1 fi if [ $RET -eq $CURRENTH ]; then ASK_TO_REBOOT=1 fi if [ $RET -eq 0 ]; then set_config_var enable_uart 1 $CONFIG HSTATUS=enabled elif [ $RET -eq 1 ]; then set_config_var enable_uart 0 $CONFIG HSTATUS=disabled else return $RET fi else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The serial login shell is $SSTATUS\nThe serial interface is $HSTATUS" 20 60 1 fi } disable_kalipi_config_at_boot() { if [ -e /etc/profile.d/kalipi-config.sh ]; then rm -f /etc/profile.d/kalipi-config.sh if [ -e /etc/systemd/system/getty@tty1.service.d/kalipi-config-override.conf ]; then rm /etc/systemd/system/getty@tty1.service.d/kalipi-config-override.conf fi telinit q fi } get_boot_cli() { if systemctl get-default | grep -q multi-user ; then echo 0 else echo 1 fi } get_autologin() { if [ $(get_boot_cli) -eq 0 ]; then # booting to CLI - check the autologin in getty or initd */ if grep -q autologin /etc/systemd/system/getty.target.wants/getty@tty1.service ; then echo 0 else echo 1 fi else # booting to desktop - check the autologin for lightdm */ if grep -q "^autologin-user=" /etc/lightdm/lightdm.conf ; then echo 0 else echo 1 fi fi } do_boot_behaviour() { OVERWRITE="/etc/systemd/system/getty@tty1.service.d/override.conf" P=$(dirname "${OVERWRITE}") ## Remove autologin if previously set if [ -f ${OVERWRITE} ]; then rm -f ${OVERWRITE} fi if [ "$INTERACTIVE" = True ]; then BOOTOPT=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Boot Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \ "B1 Console" "Text console, requiring user to login" \ "B2 Console Autologin" "Text console, automatically logged in as user of your choice" \ "B3 Desktop" "Desktop GUI, requiring user to login" \ "B4 Desktop Autologin" "Desktop GUI, automatically logged in as user of your choice" \ 3>&1 1>&2 2>&3) else BOOTOPT=$1 true fi if [ $? -eq 0 ]; then case "$BOOTOPT" in B1*) systemctl set-default multi-user.target ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service if [ -f ${OVERWRITE} ]; then rm -f ${OVERWRITE} fi ;; B2*) USER=$(whiptail --inputbox "Please enter the username for autologon\n(leave empty for $SUDO_USER):" 20 60 3>&1 1>&2 2>&3) if [ $? -ne 0 ]; then return 0 elif [ -z "$USER" ]; then USER=$SUDO_USER fi systemctl set-default multi-user.target ln -fs /etc/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service if [ ! -d ${P} ]; then mkdir -p ${P} fi cat >> ${OVERWRITE} <&1 1>&2 2>&3) if [ $? -ne 0 ]; then return 0 elif [ -z "$USER" ]; then USER=$SUDO_USER fi systemctl set-default graphical.target ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service sed /etc/lightdm/lightdm.conf -i -e "s/^\(#\|\)autologin-user=.*/autologin-user=$USER/" if [ "$USER" == "root" ]; then # Allow root login sed /etc/pam.d/lightdm-autologin -i -e "s/required pam_succeed_if.so user != root quiet_success/required pam_succeed_if.so user != anything quiet_success/" fi ## disable_kalipi_config_at_boot else whiptail --msgbox "Do 'sudo apt-get install lightdm' to allow configuration of boot to desktop" 20 60 2 return 1 fi ;; *) whiptail --msgbox "Program error, unrecognised boot option" 20 60 2 return 1 ;; esac ASK_TO_REBOOT=1 fi } get_boot_wait() { if test -e /etc/systemd/system/dhcpcd.service.d/wait.conf; then echo 0 else echo 1 fi } do_boot_wait() { DEFAULT=--defaultno if [ $(get_boot_wait) -eq 0 ]; then DEFAULT= fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like boot to wait until a network connection is established?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq 0 ]; then mkdir -p /etc/systemd/system/dhcpcd.service.d/ cat > /etc/systemd/system/dhcpcd.service.d/wait.conf << EOF [Service] ExecStart= ExecStart=/usr/lib/dhcpcd5/dhcpcd -q -w EOF STATUS=enabled elif [ $RET -eq 1 ]; then rm -f /etc/systemd/system/dhcpcd.service.d/wait.conf STATUS=disabled else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Waiting for network on boot is $STATUS" 20 60 1 fi } get_boot_splash() { if is_pi ; then if grep -q "splash" $CMDLINE ; then echo 0 else echo 1 fi else if grep -q "GRUB_CMDLINE_LINUX_DEFAULT.*splash" /etc/default/grub ; then echo 0 else echo 1 fi fi } do_boot_splash() { if [ ! -e /usr/share/plymouth/themes/pix/pix.script ]; then if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The splash screen is not installed so cannot be activated" 20 60 2 fi return 1 fi DEFAULT=--defaultno if [ $(get_boot_splash) -eq 0 ]; then DEFAULT= fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like to show the splash screen at boot?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq 0 ]; then if is_pi ; then if ! grep -q "splash" $CMDLINE ; then sed -i $CMDLINE -e "s/$/ quiet splash plymouth.ignore-serial-consoles/" fi else sed -i /etc/default/grub -e "s/GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)\"/GRUB_CMDLINE_LINUX_DEFAULT=\"\1 quiet splash plymouth.ignore-serial-consoles\"/" sed -i /etc/default/grub -e "s/ \+/ /g" sed -i /etc/default/grub -e "s/GRUB_CMDLINE_LINUX_DEFAULT=\" /GRUB_CMDLINE_LINUX_DEFAULT=\"/" update-grub fi STATUS=enabled elif [ $RET -eq 1 ]; then if is_pi ; then if grep -q "splash" $CMDLINE ; then sed -i $CMDLINE -e "s/ quiet//" sed -i $CMDLINE -e "s/ splash//" sed -i $CMDLINE -e "s/ plymouth.ignore-serial-consoles//" fi else sed -i /etc/default/grub -e "s/GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)quiet\(.*\)\"/GRUB_CMDLINE_LINUX_DEFAULT=\"\1\2\"/" sed -i /etc/default/grub -e "s/GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)splash\(.*\)\"/GRUB_CMDLINE_LINUX_DEFAULT=\"\1\2\"/" sed -i /etc/default/grub -e "s/GRUB_CMDLINE_LINUX_DEFAULT=\"\(.*\)plymouth.ignore-serial-consoles\(.*\)\"/GRUB_CMDLINE_LINUX_DEFAULT=\"\1\2\"/" sed -i /etc/default/grub -e "s/ \+/ /g" sed -i /etc/default/grub -e "s/GRUB_CMDLINE_LINUX_DEFAULT=\" /GRUB_CMDLINE_LINUX_DEFAULT=\"/" update-grub fi STATUS=disabled else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Splash screen at boot is $STATUS" 20 60 1 fi } get_rgpio() { if test -e /etc/systemd/system/pigpiod.service.d/public.conf; then echo 0 else echo 1 fi } do_rgpio() { DEFAULT=--defaultno if [ $(get_rgpio) -eq 0 ]; then DEFAULT= fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the GPIO server to be accessible over the network?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq 0 ]; then mkdir -p /etc/systemd/system/pigpiod.service.d/ cat > /etc/systemd/system/pigpiod.service.d/public.conf << EOF [Service] ExecStart= ExecStart=/usr/bin/pigpiod EOF STATUS=enabled elif [ $RET -eq 1 ]; then rm -f /etc/systemd/system/pigpiod.service.d/public.conf STATUS=disabled else return $RET fi systemctl daemon-reload if systemctl -q is-enabled pigpiod ; then systemctl restart pigpiod fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Remote access to the GPIO server is $STATUS" 20 60 1 fi } get_camera() { CAM=$(get_config_var start_x $CONFIG) if [ $CAM -eq 1 ]; then echo 0 else echo 1 fi } do_camera() { if [ ! -e /boot/start_x.elf ]; then whiptail --msgbox "Your firmware appears to be out of date (no start_x.elf). Please update" 20 60 2 return 1 fi sed $CONFIG -i -e "s/^startx/#startx/" sed $CONFIG -i -e "s/^fixup_file/#fixup_file/" DEFAULT=--defaultno CURRENT=0 if [ $(get_camera) -eq 0 ]; then DEFAULT= CURRENT=1 fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the camera interface to be enabled?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq $CURRENT ]; then ASK_TO_REBOOT=1 fi if [ $RET -eq 0 ]; then set_config_var start_x 1 $CONFIG CUR_GPU_MEM=$(get_config_var gpu_mem $CONFIG) if [ -z "$CUR_GPU_MEM" ] || [ "$CUR_GPU_MEM" -lt 128 ]; then set_config_var gpu_mem 128 $CONFIG fi STATUS=enabled elif [ $RET -eq 1 ]; then set_config_var start_x 0 $CONFIG sed $CONFIG -i -e "s/^start_file/#start_file/" STATUS=disabled else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The camera interface is $STATUS" 20 60 1 fi } get_onewire() { if grep -q -E "^dtoverlay=w1-gpio" $CONFIG; then echo 0 else echo 1 fi } do_onewire() { DEFAULT=--defaultno CURRENT=0 if [ $(get_onewire) -eq 0 ]; then DEFAULT= CURRENT=1 fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like the one-wire interface to be enabled?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq $CURRENT ]; then ASK_TO_REBOOT=1 fi if [ $RET -eq 0 ]; then sed $CONFIG -i -e "s/^#dtoverlay=w1-gpio/dtoverlay=w1-gpio/" if ! grep -q -E "^dtoverlay=w1-gpio" $CONFIG; then printf "dtoverlay=w1-gpio\n" >> $CONFIG fi STATUS=enabled elif [ $RET -eq 1 ]; then sed $CONFIG -i -e "s/^dtoverlay=w1-gpio/#dtoverlay=w1-gpio/" STATUS=disabled else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "The one-wire interface is $STATUS" 20 60 1 fi } do_gldriver() { if [ ! -e /boot/overlays/vc4-kms-v3d.dtbo ]; then whiptail --msgbox "Driver and kernel not present on your system. Please update" 20 60 2 return 1 fi if [ $(dpkg -l libgl1-mesa-dri | tail -n 1 | cut -d ' ' -f 1) != "ii" ]; then whiptail --msgbox "libgl1-mesa-dri not found - please install" 20 60 2 return 1 fi GLOPT=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "GL Driver" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT \ "G1 GL (Full KMS)" "OpenGL desktop driver with full KMS" \ "G2 GL (Fake KMS)" "OpenGL desktop driver with fake KMS" \ "G3 Legacy" "Original non-GL desktop driver" \ 3>&1 1>&2 2>&3) if [ $? -eq 0 ]; then case "$GLOPT" in G1*) if ! grep -q -E "^dtoverlay=vc4-kms-v3d" $CONFIG; then ASK_TO_REBOOT=1 fi sed $CONFIG -i -e "s/^dtoverlay=vc4-fkms-v3d/#dtoverlay=vc4-fkms-v3d/" sed $CONFIG -i -e "s/^#dtoverlay=vc4-kms-v3d/dtoverlay=vc4-kms-v3d/" if ! grep -q -E "^dtoverlay=vc4-kms-v3d" $CONFIG; then printf "dtoverlay=vc4-kms-v3d\n" >> $CONFIG fi STATUS="The full KMS GL driver is enabled." ;; G2*) if ! grep -q -E "^dtoverlay=vc4-fkms-v3d" $CONFIG; then ASK_TO_REBOOT=1 fi sed $CONFIG -i -e "s/^dtoverlay=vc4-kms-v3d/#dtoverlay=vc4-kms-v3d/" sed $CONFIG -i -e "s/^#dtoverlay=vc4-fkms-v3d/dtoverlay=vc4-fkms-v3d/" if ! grep -q -E "^dtoverlay=vc4-fkms-v3d" $CONFIG; then printf "dtoverlay=vc4-fkms-v3d\n" >> $CONFIG fi STATUS="The fake KMS GL driver is enabled." ;; G3*) if grep -q -E "^dtoverlay=vc4-f?kms-v3d" $CONFIG; then ASK_TO_REBOOT=1 fi sed $CONFIG -i -e "s/^dtoverlay=vc4-kms-v3d/#dtoverlay=vc4-kms-v3d/" sed $CONFIG -i -e "s/^dtoverlay=vc4-fkms-v3d/#dtoverlay=vc4-fkms-v3d/" STATUS="The GL driver is disabled." ;; *) whiptail --msgbox "Program error, unrecognised boot option" 20 60 2 return 1 ;; esac else return 0 fi if echo "$GLOPT" | grep -q -E "1" ; then if grep -q "splash" $CMDLINE ; then sed -i $CMDLINE -e "s/ quiet//" sed -i $CMDLINE -e "s/ splash//" sed -i $CMDLINE -e "s/ plymouth.ignore-serial-consoles//" fi sed $CONFIG -i -e "s/^gpu_mem/#gpu_mem/" fi whiptail --msgbox "$STATUS" 20 60 1 } get_net_names() { ## if grep -q "net.ifnames=0" $CMDLINE || [ "$(readlink -f /etc/systemd/network/99-default.link)" = "/dev/null" ] ; then if grep -q "net.ifnames=0" $CMDLINE || [ "$(readlink -f /etc/udev/rules.d/73-usb-net-by-mac.rules)" = "/dev/null" ] ; then echo 1 else echo 0 fi } do_net_names () { DEFAULT=--defaultno CURRENT=0 if [ $(get_net_names) -eq 0 ]; then DEFAULT= CURRENT=1 fi if [ "$INTERACTIVE" = True ]; then whiptail --yesno "Would you like to enable predictable network interface names?" $DEFAULT 20 60 2 RET=$? else RET=$1 fi if [ $RET -eq $CURRENT ]; then ASK_TO_REBOOT=1 fi if [ $RET -eq 0 ]; then sed -i $CMDLINE -e "s/net.ifnames=0 *//" rm -f /etc/udev/rules.d/73-usb-net-by-mac.rules STATUS=enabled elif [ $RET -eq 1 ]; then ln -sf /dev/null /etc/udev/rules.d/73-usb-net-by-mac.rules STATUS=disabled else return $RET fi if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Predictable network interface names are $STATUS" 20 60 1 fi } do_update() { TEMP_FILE="/tmp/kalipi-config" info UPDATE "Downloading update" wget -O ${TEMP_FILE} https://raw.githubusercontent.com/Re4son/RPi-Tweaks/master/kalipi-config/kalipi-config if [ "$(grep Re4son ${TEMP_FILE})" ]; then cp $TEMP_FILE $PROG_NAME chmod +x $PROG_NAME rm -f $TEMP_FILE info UPDATE "Replaced old version:" echo "kalipi-config Setup $VERSION" echo info UPDATE "With new version:" "$PROG_NAME" --version sleep 2 && exec "$PROG_NAME" fi } do_audio() { if [ "$INTERACTIVE" = True ]; then AUDIO_OUT=$(whiptail --menu "Choose the audio output" 20 60 10 \ "0" "Auto" \ "1" "Force 3.5mm ('headphone') jack" \ "2" "Force HDMI" \ 3>&1 1>&2 2>&3) else AUDIO_OUT=$1 fi if [ $? -eq 0 ]; then amixer cset numid=3 "$AUDIO_OUT" fi } do_resolution() { if [ "$INTERACTIVE" = True ]; then CMODE=$(get_config_var hdmi_mode $CONFIG) CGROUP=$(get_config_var hdmi_group $CONFIG) if [ $CMODE -eq 0 ] ; then CSET="Default" elif [ $CGROUP -eq 2 ] ; then CSET="DMT Mode "$CMODE else CSET="CEA Mode "$CMODE fi oIFS="$IFS" IFS="/" if tvservice -d /dev/null | grep -q Nothing ; then value="Default/720x480/DMT Mode 4/640x480 60Hz 4:3/DMT Mode 9/800x600 60Hz 4:3/DMT Mode 16/1024x768 60Hz 4:3/DMT Mode 85/1280x720 60Hz 16:9/DMT Mode 35/1280x1024 60Hz 5:4/DMT Mode 51/1600x1200 60Hz 4:3/DMT Mode 82/1920x1080 60Hz 16:9/" else value="Default/Monitor preferred resolution/" value=$value$(tvservice -m CEA | grep progressive | cut -b 12- | sed 's/mode \([0-9]\+\): \([0-9]\+\)x\([0-9]\+\) @ \([0-9]\+\)Hz \([0-9]\+\):\([0-9]\+\), clock:[0-9]\+MHz progressive/CEA Mode \1\/\2x\3 \4Hz \5:\6/' | tr '\n' '/') value=$value$(tvservice -m DMT | grep progressive | cut -b 12- | sed 's/mode \([0-9]\+\): \([0-9]\+\)x\([0-9]\+\) @ \([0-9]\+\)Hz \([0-9]\+\):\([0-9]\+\), clock:[0-9]\+MHz progressive/DMT Mode \1\/\2x\3 \4Hz \5:\6/' | tr '\n' '/') fi RES=$(whiptail --default-item $CSET --menu "Choose screen resolution" 20 60 10 ${value} 3>&1 1>&2 2>&3) STATUS=$? IFS=$oIFS if [ $STATUS -eq 0 ] ; then GRS=$(echo "$RES" | cut -d ' ' -f 1) MODE=$(echo "$RES" | cut -d ' ' -f 3) if [ $GRS = "Default" ] ; then MODE=0 elif [ $GRS = "DMT" ] ; then GROUP=2 else GROUP=1 fi fi else GROUP=$1 MODE=$2 STATUS=0 fi if [ $STATUS -eq 0 ]; then if [ $MODE -eq 0 ]; then clear_config_var hdmi_force_hotplug $CONFIG clear_config_var hdmi_group $CONFIG clear_config_var hdmi_mode $CONFIG else set_config_var hdmi_force_hotplug 1 $CONFIG set_config_var hdmi_group $GROUP $CONFIG set_config_var hdmi_mode $MODE $CONFIG fi if [ "$INTERACTIVE" = True ]; then if [ $MODE -eq 0 ] ; then whiptail --msgbox "The resolution is set to default" 20 60 1 else whiptail --msgbox "The resolution is set to $GRS mode $MODE" 20 60 1 fi fi if [ $MODE -eq 0 ] ; then TSET="Default" elif [ $GROUP -eq 2 ] ; then TSET="DMT Mode "$MODE else TSET="CEA Mode "$MODE fi if [ "$TSET" != "$CSET" ] ; then ASK_TO_REBOOT=1 fi fi } list_wlan_interfaces() { for dir in /sys/class/net/*/wireless; do if [ -d "$dir" ]; then basename "$(dirname "$dir")" fi done } do_wifi_ssid_passphrase() { WPASUPPCONF="/etc/wpa_supplicant/wpa_supplicant.conf" INTERFACES="/etc/network/interfaces" RESTART_IF=0 RET=0 IFACE_LIST="$(list_wlan_interfaces)" IFACE="$(echo "$IFACE_LIST" | head -n 1)" if [ -z "$IFACE" ]; then if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "No wireless interface found" 20 60 fi return 1 fi sed /etc/dhcp/dhclient.conf -i -e "s/^\(#\|\)timeout .*;/timeout 10;/" nm_status=$(/bin/systemctl status network-manager) if [[ $nm_status = *"is running"* ]] || [[ $nm_status = *"active (running)"* ]]; then systemctl stop network-manager && systemctl disable network-manager echo "is running" fi IS_IF_DEFINED=$(grep "${IFACE}" $INTERFACES) if [ -z "$IS_IF_DEFINED" ]; then cat >> $INTERFACES < "$WPASUPPCONF" RESTART_IF=1 fi IS_UPDATE_CONFIG_DEFINED=$(grep "update_config" $WPASUPPCONF) IS_UPDATE_CONFIG_ZERO=$(grep "update_config=0" $WPASUPPCONF) if [ -z "$IS_UPDATE_CONFIG_DEFINED" ]; then sed -i '1s/^/update_config=1\n/' $WPASUPPCONF RESTART_IF=1 elif [ ! -z "$IS_UPDATE_CONFIG_ZERO" ]; then sed -i 's/update_config=0/update_config=1/' $WPASUPPCONF echo "UPDATE_CONFIG_IS_ZERO" RESTART_IF=1 fi IS_CTRL_DEFINED=$(grep "ctrl_interface" $WPASUPPCONF) if [ -z "$IS_CTRL_DEFINED" ] ; then sed -i '1s/^/ctrl_interface=DIR=\/var\/run\/wpa_supplicant GROUP=netdev\n/' $WPASUPPCONF RESTART_IF=1 fi if ! wpa_cli -i "$IFACE" status > /dev/null 2>&1; then RESTART_IF=1 fi if [ "$RESTART_IF" -eq 1 ]; then ifdown $IFACE sleep 2 ifup $IFACE fi if ! wpa_cli -i "$IFACE" status > /dev/null 2>&1; then if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Could not communicate with wpa_supplicant" 20 60 fi return 1 fi AVAIL_SSID=$(/sbin/iw wlan0 scan|grep SSID) whiptail --msgbox "Available WiFi Networks (Tip: use copy and paste):\n\n$AVAIL_SSID" 20 90 SSID="$1" while [ -z "$SSID" ] && [ "$INTERACTIVE" = True ]; do SSID=$(whiptail --inputbox "Please enter SSID" 20 60 3>&1 1>&2 2>&3) if [ $? -ne 0 ]; then return 0 elif [ -z "$SSID" ]; then whiptail --msgbox "SSID cannot be empty. Please try again." 20 60 fi done PASSPHRASE="$2" while [ "$INTERACTIVE" = True ]; do PASSPHRASE=$(whiptail --passwordbox "Please enter passphrase. Leave it empty if none." 20 60 3>&1 1>&2 2>&3) if [ $? -ne 0 ]; then return 0 else break fi done # Escape special characters for embedding in regex below local ssid="$(echo "$SSID" \ | sed 's;\\;\\\\;g' \ | sed -e 's;\.;\\\.;g' \ -e 's;\*;\\\*;g' \ -e 's;\+;\\\+;g' \ -e 's;\?;\\\?;g' \ -e 's;\^;\\\^;g' \ -e 's;\$;\\\$;g' \ -e 's;\/;\\\/;g' \ -e 's;\[;\\\[;g' \ -e 's;\];\\\];g' \ -e 's;{;\\{;g' \ -e 's;};\\};g' \ -e 's;(;\\(;g' \ -e 's;);\\);g' \ -e 's;";\\\\\";g')" wpa_cli -i "$IFACE" list_networks \ | tail -n +2 | cut -f -2 | grep -P "\t$ssid$" | cut -f1 \ | while read ID; do wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1 done ID="$(wpa_cli -i "$IFACE" add_network)" wpa_cli -i "$IFACE" set_network "$ID" ssid "\"$SSID\"" 2>&1 | grep -q "OK" RET=$((RET + $?)) if [ -z "$PASSPHRASE" ]; then wpa_cli -i "$IFACE" set_network "$ID" key_mgmt NONE 2>&1 | grep -q "OK" RET=$((RET + $?)) else wpa_cli -i "$IFACE" set_network "$ID" psk "\"$PASSPHRASE\"" 2>&1 | grep -q "OK" RET=$((RET + $?)) fi if [ $RET -eq 0 ]; then wpa_cli -i "$IFACE" enable_network "$ID" > /dev/null 2>&1 else wpa_cli -i "$IFACE" remove_network "$ID" > /dev/null 2>&1 if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "Failed to set SSID or passphrase" 20 60 fi fi wpa_cli -i "$IFACE" save_config > /dev/null 2>&1 ## Replace the passphrase with a hash in wpa_supplicant.conf PASSHASH="$(wpa_passphrase "$SSID" "$PASSPHRASE"|grep -e "^\spsk"| sed -e 's/^\s*//')" sed /etc/wpa_supplicant/wpa_supplicant.conf -i -e "s/psk=\"$PASSPHRASE\"/$PASSHASH/" echo "$IFACE_LIST" | while read IFACE; do wpa_cli -i "$IFACE" reconfigure > /dev/null 2>&1 done ifdown $IFACE sleep 2 ifup $IFACE return $RET } do_swap_nexmon_firmware() { local is_43430_nexmon="$(strings "/lib/firmware/brcm/brcmfmac43430-sdio.bin"|grep nexmon)" if [ ! -f /lib/firmware/brcm/brcmfmac43430-sdio.nexmon.bin ]; then if [ ! "" == "$is_43430_nexmon" ]; then cp -f /lib/firmware/brcm/brcmfmac43430-sdio.bin /lib/firmware/brcm/brcmfmac43430-sdio.nexmon.bin else whiptail --msgbox "No nexmon firmware found.\nInstall the Re4son-Kernel and try again." 20 60 return fi fi if [ ! -f /lib/firmware/brcm/brcmfmac43430-sdio.rpi.bin ]; then wget https://raw.githubusercontent.com/RPi-Distro/firmware-nonfree/master/brcm/brcmfmac43430-sdio.bin -O /lib/firmware/brcm/brcmfmac43430-sdio.rpi.bin if [ ! -f /lib/firmware/brcm/brcmfmac43430-sdio.rpi.bin ]; then whiptail --msgbox "No OEM firmware found.\n Download OEM firmware to /lib/firmware/brcm/brcmfmac43430-sdio.rpi.bin and try again." 20 60 return fi fi if [ ! "" == "$is_43430_nexmon" ]; then whiptail --yesno "Nexmon firmware is currently installed. Would you like to replace it with OEM firmware?" $DEFAULT 20 60 2 RET=$? if [ $RET -eq 0 ]; then cp -f /lib/firmware/brcm/brcmfmac43430-sdio.rpi.bin /lib/firmware/brcm/brcmfmac43430-sdio.bin whiptail --msgbox "OEM firmware successfully installed." 20 60 fi else whiptail --yesno "OEM firmware is currently installed. Would you like to replace it with nexmon firmware?" $DEFAULT 20 60 2 RET=$? if [ $RET -eq 0 ]; then cp -f /lib/firmware/brcm/brcmfmac43430-sdio.nexmon.bin /lib/firmware/brcm/brcmfmac43430-sdio.bin whiptail --msgbox "Nexmon firmware successfully installed." 20 60 fi fi rmmod brcmfmac modprobe brcmfmac return } do_swap_nexmon_firmware_plus() { local is_43455_nexmon="$(strings "/lib/firmware/brcm/brcmfmac43455-sdio.bin"|grep nexmon)" if [ ! -f /lib/firmware/brcm/brcmfmac43455-sdio.nexmon.bin ]; then if [ ! "" == "$is_43455_nexmon" ]; then cp -f /lib/firmware/brcm/brcmfmac43455-sdio.bin /lib/firmware/brcm/brcmfmac43455-sdio.nexmon.bin else whiptail --msgbox "No nexmon firmware found.\nInstall the Re4son-Kernel and try again." 20 60 return fi fi if [ ! -f /lib/firmware/brcm/brcmfmac43455-sdio.rpi.bin ]; then wget https://raw.githubusercontent.com/RPi-Distro/firmware-nonfree/master/brcm/brcmfmac43455-sdio.bin -O /lib/firmware/brcm/brcmfmac43455-sdio.rpi.bin if [ ! -f /lib/firmware/brcm/brcmfmac43455-sdio.rpi.bin ]; then whiptail --msgbox "No OEM firmware found.\n Download OEM firmware to /lib/firmware/brcm/brcmfmac43455-sdio.rpi.bin and try again." 20 60 return fi fi if [ ! "" == "$is_43455_nexmon" ]; then whiptail --yesno "Nexmon firmware is currently installed. Would you like to replace it with OEM firmware?" $DEFAULT 20 60 2 RET=$? if [ $RET -eq 0 ]; then cp -f /lib/firmware/brcm/brcmfmac43455-sdio.rpi.bin /lib/firmware/brcm/brcmfmac43455-sdio.bin whiptail --msgbox "OEM firmware successfully installed." 20 60 fi else whiptail --yesno "OEM firmware is currently installed. Would you like to replace it with nexmon firmware?" $DEFAULT 20 60 2 RET=$? if [ $RET -eq 0 ]; then cp -f /lib/firmware/brcm/brcmfmac43455-sdio.nexmon.bin /lib/firmware/brcm/brcmfmac43455-sdio.bin whiptail --msgbox "Nexmon firmware successfully installed." 20 60 fi fi rmmod brcmfmac modprobe brcmfmac return } do_finish() { ## disable_kalipi_config_at_boot if [ $ASK_TO_REBOOT -eq 1 ]; then whiptail --yesno "Would you like to reboot now?" 20 60 2 if [ $? -eq 0 ]; then # yes sync reboot fi fi exit 0 } # $1 = filename, $2 = key name get_json_string_val() { sed -n -e "s/^[[:space:]]*\"$2\"[[:space:]]*:[[:space:]]*\"\(.*\)\"[[:space:]]*,$/\1/p" $1 } # TODO: This is probably broken do_apply_os_config() { [ -e /boot/os_config.json ] || return 0 NOOBSFLAVOUR=$(get_json_string_val /boot/os_config.json flavour) NOOBSLANGUAGE=$(get_json_string_val /boot/os_config.json language) NOOBSKEYBOARD=$(get_json_string_val /boot/os_config.json keyboard) if [ -n "$NOOBSFLAVOUR" ]; then printf "Setting flavour to %s based on os_config.json from NOOBS. May take a while\n" "$NOOBSFLAVOUR" printf "Unrecognised flavour. Ignoring\n" fi # TODO: currently ignores en_gb settings as we assume we are running in a # first boot context, where UK English settings are default case "$NOOBSLANGUAGE" in "en") if [ "$NOOBSKEYBOARD" = "gb" ]; then DEBLANGUAGE="" # UK english is the default, so ignore else DEBLANGUAGE="en_US.UTF-8" fi ;; "de") DEBLANGUAGE="de_DE.UTF-8" ;; "fi") DEBLANGUAGE="fi_FI.UTF-8" ;; "fr") DEBLANGUAGE="fr_FR.UTF-8" ;; "hu") DEBLANGUAGE="hu_HU.UTF-8" ;; "ja") DEBLANGUAGE="ja_JP.UTF-8" ;; "nl") DEBLANGUAGE="nl_NL.UTF-8" ;; "pt") DEBLANGUAGE="pt_PT.UTF-8" ;; "ru") DEBLANGUAGE="ru_RU.UTF-8" ;; "zh_CN") DEBLANGUAGE="zh_CN.UTF-8" ;; *) printf "Language '%s' not handled currently. Run sudo kalipi-config to set up" "$NOOBSLANGUAGE" ;; esac if [ -n "$DEBLANGUAGE" ]; then printf "Setting language to %s based on os_config.json from NOOBS. May take a while\n" "$DEBLANGUAGE" do_change_locale "$DEBLANGUAGE" fi if [ -n "$NOOBSKEYBOARD" -a "$NOOBSKEYBOARD" != "gb" ]; then printf "Setting keyboard layout to %s based on os_config.json from NOOBS. May take a while\n" "$NOOBSKEYBOARD" do_configure_keyboard "$NOOBSKEYBOARD" fi return 0 } nonint() { "$@" } # # Command line options for non-interactive use # for i in $* do case $i in --version) INTERACTIVE=False print_version exit 1 ;; --memory-split) OPT_MEMORY_SPLIT=GET printf "Not currently supported\n" exit 1 ;; --memory-split=*) OPT_MEMORY_SPLIT=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` printf "Not currently supported\n" exit 1 ;; --expand-rootfs) INTERACTIVE=False do_expand_rootfs printf "Please reboot\n" exit 0 ;; --apply-os-config) INTERACTIVE=False do_apply_os_config exit $? ;; nonint) INTERACTIVE=False "$@" exit $? ;; *) # unknown option ;; esac done if [ "GET" = "${OPT_MEMORY_SPLIT:-}" ]; then set -u # Fail on unset variables get_current_memory_split echo $CURRENT_MEMSPLIT exit 0 fi # Everything else needs to be run as root if [ $(id -u) -ne 0 ]; then printf "\nProgram must be run as root. Try 'sudo kalipi-config'\n\n" exit 1 fi if [ -n "${OPT_MEMORY_SPLIT:-}" ]; then set -e # Fail when a command errors set_memory_split "${OPT_MEMORY_SPLIT}" exit 0 fi # Check dependencies PROGRAMS=("whiptail" "parted" "lua" "pstree" "amixer") PACKAGES=("whiptail" "parted" "lua5.1" "psmisc" "alsa-utils") missingprogs="" missingpkgs="" for i in "${!PROGRAMS[@]}"; do if [ $(check_bin ${PROGRAMS[$i]}) -eq 0 ]; then missingpkgs="${missingpkgs}${PACKAGES[$i]} " fi done if [ "" != "$missingpkgs" ]; then printf "\nThe following packages are missing: $missingpkgs\n" printf "Please install them before continuing, i.e.:\n" printf "\nsudo apt install $missingpkgs\n\n" exit 1 fi # And we want /boot to be mounted if ! grep -q boot /proc/mounts; then mount /boot fi if ! grep -q boot /proc/mounts; then printf "\n/boot must be mounted. Try 'mount /boot'\n\n" exit 1 fi set_sudo_user do_internationalisation_menu() { calc_wt_size FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Localisation Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \ "I1 Change Locale" "Set up language and regional settings to match your location" \ "I2 Change Timezone" "Set up timezone to match your location" \ "I3 Change Keyboard Layout" "Set the keyboard layout to match your keyboard" \ "I4 Change Wi-fi Country" "Set the legal channels used in your country" \ 3>&1 1>&2 2>&3) RET=$? if [ $RET -eq 1 ]; then return 0 elif [ $RET -eq 0 ]; then case "$FUN" in I1\ *) do_change_locale ;; I2\ *) do_change_timezone ;; I3\ *) do_configure_keyboard ;; I4\ *) do_wifi_country ;; *) whiptail --msgbox "Program error: unrecognized option" 20 60 1 ;; esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1 fi } do_interface_menu() { calc_wt_size FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Interfacing Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \ "P1 Camera" "Enable/Disable connection to the Raspberry Pi Camera" \ "P2 SSH" "Enable/Disable remote command line access to your Pi using SSH" \ "P3 SPI" "Enable/Disable automatic loading of SPI kernel module" \ "P4 I2C" "Enable/Disable automatic loading of I2C kernel module" \ "P5 Serial" "Enable/Disable shell and kernel messages on the serial connection" \ "P6 1-Wire" "Enable/Disable one-wire interface" \ "P7 Remote GPIO" "Enable/Disable remote access to GPIO pins" \ 3>&1 1>&2 2>&3) RET=$? if [ $RET -eq 1 ]; then return 0 elif [ $RET -eq 0 ]; then case "$FUN" in P1\ *) do_camera ;; P2\ *) do_ssh ;; P3\ *) do_spi ;; P4\ *) do_i2c ;; P5\ *) do_serial ;; P6\ *) do_onewire ;; P7\ *) do_rgpio ;; *) whiptail --msgbox "Program error: unrecognized option" 20 60 1 ;; esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1 fi } do_advanced_menu() { calc_wt_size FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Advanced Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \ "A1 Expand Filesystem" "Ensures that all of the SD card storage is available to the OS" \ "A2 Overscan" "You may need to configure overscan if black bars are present on display" \ "A3 Memory Split" "Change the amount of memory made available to the GPU" \ "A4 Audio" "Force audio out through HDMI or 3.5mm jack" \ "A5 Resolution" "Set a specific screen resolution" \ "A6 Pixel Doubling" "Enable/Disable 2x2 pixel mapping" \ "A7 GL Driver" "Enable/Disable experimental desktop GL driver" \ 3>&1 1>&2 2>&3) RET=$? if [ $RET -eq 1 ]; then return 0 elif [ $RET -eq 0 ]; then case "$FUN" in A1\ *) do_expand_rootfs ;; A2\ *) do_overscan ;; A3\ *) do_memory_split ;; A4\ *) do_audio ;; A5\ *) do_resolution ;; A6\ *) do_pixdub ;; A7\ *) do_gldriver ;; *) whiptail --msgbox "Program error: unrecognized option" 20 60 1 ;; esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1 fi } do_boot_menu() { calc_wt_size if is_live ; then FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Boot Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \ "B1 Desktop / CLI" "Choose whether to boot into a desktop environment or the command line" \ "B2 Wait for Network at Boot" "Choose whether to wait for network connection during boot" \ 3>&1 1>&2 2>&3) else FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Boot Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \ "B1 Desktop / CLI" "Choose whether to boot into a desktop environment or the command line" \ "B2 Wait for Network at Boot" "Choose whether to wait for network connection during boot" \ 3>&1 1>&2 2>&3) fi RET=$? if [ $RET -eq 1 ]; then return 0 elif [ $RET -eq 0 ]; then case "$FUN" in B1\ *) do_boot_behaviour ;; B2\ *) do_boot_wait ;; *) whiptail --msgbox "Program error: unrecognized option" 20 60 1 ;; esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1 fi } do_network_menu() { calc_wt_size FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Network Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Back --ok-button Select \ "N1 Hostname" "Set the visible name for this Pi on a network" \ "N2 Wi-fi" "Enter SSID and passphrase" \ "N3 Network interface names" "Enable/Disable predictable network interface names" \ "N4 Swap 43430 firmware" "Swap nexmon firmware and OEM firmware for Raspberry Pi 0W/3" \ "N5 Swap 43455 firmware" "Swap nexmon firmware and OEM firmware for Raspberry Pi 3+" \ 3>&1 1>&2 2>&3) RET=$? if [ $RET -eq 1 ]; then return 0 elif [ $RET -eq 0 ]; then case "$FUN" in N1\ *) do_hostname ;; N2\ *) do_wifi_ssid_passphrase ;; N3\ *) do_net_names ;; N4\ *) do_swap_nexmon_firmware ;; N5\ *) do_swap_nexmon_firmware_plus ;; *) whiptail --msgbox "Program error: unrecognized option" 20 60 1 ;; esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1 fi } # # Interactive use loop # if [ "$INTERACTIVE" = True ]; then [ -e $CONFIG ] || touch $CONFIG calc_wt_size while true; do if is_pi ; then FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --backtitle "$(cat /proc/device-tree/model| tr -d '\0')" --menu "Setup Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Finish --ok-button Select \ "01 Change User Password" "Change password for any user" \ "02 Network Options" "Configure network settings" \ "03 Boot Options" "Configure options for start-up" \ "04 Localisation Options" "Set up language and regional settings to match your location" \ "05 Interfacing Options" "Configure connections to peripherals" \ "06 Overclock" "Configure overclocking for your Pi" \ "07 Advanced Options" "Configure advanced settings" \ "08 Kali-Pi TFT Config" "Run the kalipi-tft-config tool to set up a tft screen" \ "09 Update" "Update this tool to the latest version" \ "10 About kalipi-config" "Information about this configuration tool" \ 3>&1 1>&2 2>&3) else FUN=$(whiptail --title "Kali-Pi Software Configuration Tool (kalipi-config)" --menu "Setup Options" $WT_HEIGHT $WT_WIDTH $WT_MENU_HEIGHT --cancel-button Finish --ok-button Select \ "01 Change User Password" "Change password for the current user" \ "02 Network Options" "Configure network settings" \ "03 Boot Options" "Configure options for start-up" \ "04 Localisation Options" "Set up language and regional settings to match your location" \ "05 SSH" "Enable/Disable remote command line access to your PC using SSH" \ "06 Pixel Doubling" "Enable/Disable 2x2 pixel mapping" \ "08 Kali-Pi TFT Config" "Run the kalipi-tft-config tool to set up a tft screen" \ "09 Update" "Update this tool to the latest version" \ "10 About kalipi-config" "Information about this configuration tool" \ 3>&1 1>&2 2>&3) fi RET=$? if [ $RET -eq 1 ]; then do_finish elif [ $RET -eq 0 ]; then if is_pi ; then case "$FUN" in 01\ *) do_change_pass ;; 02\ *) do_network_menu ;; 03\ *) do_boot_menu ;; 04\ *) do_internationalisation_menu ;; 05\ *) do_interface_menu ;; 06\ *) do_overclock ;; 07\ *) do_advanced_menu ;; 08\ *) do_kalipi_tft_config;; 09\ *) do_update;; 10\ *) do_about ;; *) whiptail --msgbox "Program error: unrecognized option" 20 60 1 ;; esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1 else case "$FUN" in 01\ *) do_change_pass ;; 02\ *) do_network_menu ;; 03\ *) do_boot_menu ;; 04\ *) do_internationalisation_menu ;; 05\ *) do_ssh ;; 06\ *) do_pixdub ;; 08\ *) do_kalipi_tft_config;; 09\ *) do_update ;; 10\ *) do_about ;; *) whiptail --msgbox "Program error: unrecognized option" 20 60 1 ;; esac || whiptail --msgbox "There was an error running option $FUN" 20 60 1 fi else exit 1 fi done fi