添加构建Allwinner H616四核2GB RAM SoC WiFi(蓝莓)

This commit is contained in:
root
2023-09-19 11:24:52 +08:00
commit c97506efcc
10383 changed files with 16797445 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
[system]
start_os_name = linux
timeout = -1
display_device= -1
display_mode = 0
erase_flash = 1
[linux]

View File

@@ -0,0 +1,8 @@
[segment]
img_name = c:\u-boot.bin
img_size = 0x80000
img_base = 0x4A000000
[script_info]
script_base = 0x43000000
script_size = 0x10000

View File

@@ -0,0 +1,5 @@
[system]
start_os_name = linux
timeout = -1
display_device= 0
display_mode = 0

View File

@@ -0,0 +1,8 @@
[segment]
img_name = c:\linux\u-boot.bin
img_size = 0x80000
img_base = 0x4A000000
[script_info]
script_base = 0x43000000
script_size = 0x10000

View File

@@ -0,0 +1,5 @@
[system]
start_os_name = linux
timeout = -1
display_device= 0
display_mode = 0

View File

@@ -0,0 +1,8 @@
[segment]
img_name = c:\linux\u-boot.bin
img_size = 0x80000
img_base = 0x4A000000
[script_info]
script_base = 0x43000000
script_size = 0x10000

View File

@@ -0,0 +1,10 @@
/boot/*
/dev/*
/proc/*
/sys/*
/media/*
/mnt/*
/run/*
/tmp/*
/ddbr/*
/var/log/journal

View File

@@ -0,0 +1,92 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
function getboardtemp() {
if [ -f /etc/armbianmonitor/datasources/soctemp ]; then
read raw_temp </etc/armbianmonitor/datasources/soctemp 2>/dev/null
if [ ! -z $(echo "$raw_temp" | grep -o "^[1-9][0-9]*\.\?[0-9]*$") ] && (( $(echo "${raw_temp} < 200" |bc -l) )); then
# Allwinner legacy kernels output degree C
board_temp=${raw_temp}
else
board_temp=$(awk '{printf("%d",$1/1000)}' <<<${raw_temp})
fi
elif [ -f /etc/armbianmonitor/datasources/pmictemp ]; then
# fallback to PMIC temperature
board_temp=$(awk '{printf("%d",$1/1000)}' </etc/armbianmonitor/datasources/pmictemp)
fi
# Some boards, such as the Orange Pi Zero LTS, report shifted CPU temperatures
board_temp=$((board_temp + CPU_TEMP_OFFSET))
} # getboardtemp
function batteryinfo() {
# Battery info for Allwinner
mainline_dir="/sys/power/axp_pmu"
legacy_dir="/sys/class/power_supply"
if [[ -e "$mainline_dir" ]]; then
read status_battery_connected < $mainline_dir/battery/connected 2>/dev/null
if [[ "$status_battery_connected" == "1" ]]; then
read status_battery_charging < $mainline_dir/charger/charging
read status_ac_connect < $mainline_dir/ac/connected
read battery_percent< $mainline_dir/battery/capacity
# dispay charging / percentage
if [[ "$status_ac_connect" == "1" && "$battery_percent" -lt "100" ]]; then
status_battery_text=" charging"
elif [[ "$status_ac_connect" == "1" && "$battery_percent" -eq "100" ]]; then
status_battery_text=" charged"
else
status_battery_text=" discharging"
fi
fi
elif [[ -e "$legacy_dir/axp813-ac" ]]; then
read status_battery_connected < $legacy_dir/axp20x-battery/present
if [[ "$status_battery_connected" == "1" ]]; then
status_battery_text=" "$(awk '{print tolower($0)}' < $legacy_dir/axp20x-battery/status)
read status_ac_connect < $legacy_dir/axp813-ac/present
read battery_percent< $legacy_dir/axp20x-battery/capacity
fi
elif [[ -e "$legacy_dir/battery" ]]; then
if [[ (("$(cat $legacy_dir/battery/voltage_now)" -gt "5" )) ]]; then
status_battery_text=" "$(awk '{print tolower($0)}' < $legacy_dir/battery/status)
read battery_percent <$legacy_dir/battery/capacity
fi
fi
} # batteryinfo
function ambienttemp() {
# define where w1 usually shows up
W1_DIR="/sys/devices/w1_bus_master1/"
if [ -f /etc/armbianmonitor/datasources/ambienttemp ]; then
read raw_temp </etc/armbianmonitor/datasources/ambienttemp 2>/dev/null
amb_temp=$(awk '{printf("%d",$1/1000)}' <<<${raw_temp})
echo $amb_temp
elif [[ -d $W1_DIR && $ONE_WIRE == yes ]]; then
device=$(ls -1 $W1_DIR | grep -E '^[0-9]{1,4}' | head -1)
if [[ -n $device ]]; then
read raw_temp < ${W1_DIR}${device}/hwmon/$(ls -1 ${W1_DIR}${device}/hwmon)/temp1_input 2>/dev/null
amb_temp=$(awk '{printf("%d",$1/1000)}' <<<${raw_temp})
echo $amb_temp
fi
else
# read ambient temperature from USB device if available
if [[ ! -f /usr/bin/temper ]]; then
echo ""
return
fi
amb_temp=$(temper -c 2>/dev/null)
case ${amb_temp} in
*"find the USB device"*)
echo ""
;;
*)
amb_temp=$(awk '{print $NF}' <<<$amb_temp | sed 's/C//g')
echo -n "scale=1;${amb_temp}/1" | grep -oE "\-?[[:digit:]]+\.[[:digit:]]"
esac
fi
} # ambienttemp

View File

@@ -0,0 +1,64 @@
#!/bin/bash
#
# 40-updates - create the list of packages for update with caching
# Copyright (c) 2015 Arkadiusz Raj
#
# Author: Arkadiusz Raj arek.raj@gmail.com
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
lock_file='/var/run/armbian-motd-updates.lock'
if { set -C; 2>/dev/null >${lock_file}; }; then
trap "rm -f ${lock_file}" EXIT
else
exit 0
fi
# give up if packages are broken
[[ $(dpkg -l | grep ^..r) ]] && exit 0
# give up if there is a dependency problem
[[ "$((apt-get upgrade -s -qq) 2>&1)" == *"Unmet dependencies"* ]] && exit 0
myfile="/var/cache/apt/archives/updates.number"
myfiles="/var/cache/apt/archives/updates.list"
# update procedure
DISTRO=$(lsb_release -c | cut -d ":" -f 2 | tr -d '[:space:]') && DISTRO=${DISTRO,,}
# run around the packages
upgrades=0
security_upgrades=0
while IFS= read -r LINE; do
# increment the upgrade counter
(( upgrades++ ))
# keep another count for security upgrades
[[ ${LINE} == *"${DISTRO}-sec"* ]] && (( security_upgrades++ ))
done < <(apt-get upgrade -s -qq | sed -n '/^Inst/p')
cat >|${myfile} <<EOT
NUM_UPDATES="${upgrades}"
NUM_UPDATES_ONHOLD="$(dpkg --list | grep ^hi | grep $(uname -r) | wc -l)"
NUM_SECURITY_UPDATES="${security_upgrades}"
DATE="$(date +"%Y-%m-%d %H:%M")"
EOT
# store packages list
dpkg --list | grep ^hi | grep $(uname -r) | awk '{ print $2 }' >| ${myfiles}
exit 0

View File

@@ -0,0 +1,160 @@
#!/usr/bin/env bash
# Check that we have the tools required available, otherwise exit with no error.
# Use command -v, not which, which is deprecated.
[[ -z $(command -v amixer) ]] && echo "Missing amixer; doing nothing." && exit 0
[[ -z $(command -v alsactl) ]] && echo "Missing alsactl; doing nothing." && exit 0
[[ -z $(command -v aplay) ]] && echo "Missing aplay; doing nothing." && exit 0
mixer_cmds() {
parm=${3:-on}
echo "sset '$1' '$2' '$parm'"
echo "sset '$1' '$parm'"
}
if [ -f "$HOME/.config/sound.conf" ]; then
alsactl restore -f "$HOME/.config/sound.conf"
else
# get card num
#card=`echo $1 | sed 's/[^0-9]*//g'`
card1=$(aplay -l | grep "device 0" | awk '{print $3}')
#echo $card
for card in $card1; do (
#echo $card
# set common mixer params
mixer_cmds Master 0db
mixer_cmds Front 100%
mixer_cmds PCM 0db
mixer_cmds Synth 100%
# mute CD, since using digital audio instead
mixer_cmds CD 0% mute
# Only unmute Line and Aux if they are possibly used.
# mixer_cmds Line 100%
# mixer_cmds Aux 100%
# mute mic
mixer_cmds Mic 0% mute
# ESS 1969 chipset has 2 PCM channels
mixer_cmds PCM,1 100%
# Trident/YMFPCI/emu10k1
mixer_cmds Wave 100%
mixer_cmds Music 100%
mixer_cmds AC97 100%
mixer_cmds Surround 90%
mixer_cmds 'Surround Digital' 90%
mixer_cmds 'Wave Surround' 90%
mixer_cmds 'Duplicate Front' 90%
mixer_cmds 'Sigmatel 4-Speaker Stereo' 90%
# CS4237B chipset:
mixer_cmds 'Master Digital' 100%
# DRC
mixer_cmds 'Dynamic Range Compression' 90%
# Envy24 chips with analog outs
mixer_cmds DAC 100%
mixer_cmds DAC,0 100%
mixer_cmds DAC,1 100%
# some notebooks use headphone instead of master
mixer_cmds Headphone 100%
mixer_cmds Speaker 100%
mixer_cmds 'Internal Speaker' 0% mute
mixer_cmds Playback 100%
mixer_cmds Headphone 100%
mixer_cmds Speaker 100%
mixer_cmds Center 100%
mixer_cmds LFE 100%
mixer_cmds Center/LFE 100%
# Intel P4P800-MX (Ubuntu bug #5813)
mixer_cmds 'Master Playback Switch' on
# set digital output mixer params
mixer_cmds 'IEC958' 100% on
mixer_cmds 'IEC958 Output' 100%
mixer_cmds 'IEC958 Coaxial' 100%
mixer_cmds 'IEC958 LiveDrive' 100%
mixer_cmds 'IEC958 Optical Raw' 100%
mixer_cmds 'SPDIF Out' 100%
mixer_cmds 'SPDIF Front' 100%
mixer_cmds 'SPDIF Rear' 100%
mixer_cmds 'SPDIF Center/LFE' 100%
mixer_cmds 'Master Digital' 100%
mixer_cmds 'Analog Front' 100%
mixer_cmds 'Analog Rear' 100%
mixer_cmds 'Analog Center/LFE' 100%
# ASRock ION 330 (and perhaps others) has 2 IEC958 channels
mixer_cmds IEC958,0 on
mixer_cmds IEC958,1 on
# some ION2 has much more IEC958 channels ...
mixer_cmds IEC958,2 on
mixer_cmds IEC958,3 on
# ASRock ION 330 has Master Front set to 0
mixer_cmds 'Master Front' 100%
# Shuttle XS35GT needs this too
mixer_cmds 'Master',0 100% on
# and this for various Fusion devices like Zotac ZBOX
mixer_cmds 'Front',0 100% on
# NVidia CK804 sound devices
mixer_cmds 'IEC958 Playback AC97-SPSA' 100%
# Allwinner H3 Analog
mixer_cmds 'Line Out' 0db on
# Allwinner A20 Analog
mixer_cmds 'Power Amplifier' 0db
mixer_cmds 'Power Amplifier DAC' on
mixer_cmds 'Power Amplifier Mute' on
# Allwinner A64 Analog
mixer_cmds Headphone 0db on
mixer_cmds 'AIF1 Slot 0 Digital DAC' on
# Amlogic G12 HDMI to PCM0
mixer_cmds 'FRDDR_A SINK 1 SEL' 'OUT 1'
mixer_cmds 'FRDDR_A SRC 1 EN' on
mixer_cmds 'TDMOUT_B SRC SEL' 'IN 0'
mixer_cmds 'TOHDMITX I2S SRC' 'I2S B'
mixer_cmds 'TOHDMITX' on
# Amlogic G12 S/PDIF to PCM1
mixer_cmds 'FRDDR_B SINK 1 SEL' 'OUT 3'
mixer_cmds 'FRDDR_B SRC 1 EN' on
mixer_cmds 'SPDIFOUT SRC SEL' 'IN 1'
mixer_cmds 'SPDIFOUT Playback' on
# Amlogic GX HDMI and S/PDIF
mixer_cmds 'AIU HDMI CTRL SRC' 'I2S'
mixer_cmds 'AIU SPDIF SRC SEL' 'SPDIF'
# RockPI 4B Analog
mixer_cmds 'Right Headphone Mixer Right DAC' on
mixer_cmds 'Left Headphone Mixer Left DAC' on
# NanoPC T4 Analog
mixer_cmds 'HPO L' on
mixer_cmds 'HPO R' on
mixer_cmds 'HPOVOL L' on
mixer_cmds 'HPOVOL R' on
mixer_cmds 'HPO MIX HPVOL' on
mixer_cmds 'OUT MIXL DAC L1' on
mixer_cmds 'OUT MIXR DAC R1' on
mixer_cmds 'Stereo DAC MIXL DAC L1' on
mixer_cmds 'Stereo DAC MIXR DAC R1' on
) | amixer -c "$card" --stdin > /dev/null 2>&1; done
fi

View File

@@ -0,0 +1,29 @@
#!/bin/bash
set -o nounset
set -o errexit
set -o pipefail
shopt -s dotglob
# SPDX-License-Identifier: MIT
# This script should be executed every 5 minutes by a cron job `/etc/cron.d/armbian-check-battery`.
# It checks if battery is discharging and battery level is more than 10%. If less, then start a system shutdown.
# Script uses `batteryinfo` function from `30-armbian-sysinfo` file of Armbian distribution.
BATTERY_PERCENT_MIN='10'
# Include functions:
# getboardtemp()
# batteryinfo()
# ambienttemp()
source /usr/lib/armbian/armbian-allwinner-battery
batteryinfo
# `status_battery_text` has a leading whitespace
if [ "$status_battery_connected" == '1' ] && [[ "$status_battery_text" =~ [[:space:]]*discharging ]]; then
# When no battery connected, variable `battery_percent` is not defined!
if [ "$battery_percent" -lt "$BATTERY_PERCENT_MIN" ]; then
logger --tag cron_check_battery_shutdown "battery_percent = $battery_percent, running shutdown"
shutdown -h +1
fi
fi

View File

@@ -0,0 +1,60 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
# Functions:
#
# show_motd_warning
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
my_name="${0##*/}"
Log=/var/log/armbian-hardware-monitor.log
show_motd_warning() {
cat > /etc/update-motd.d/90-warning <<EOT
#!/bin/bash
echo -e "\e[0;91mAttention:\x1B[0m $1\n"
rm "\$0"
EOT
chmod +x /etc/update-motd.d/90-warning
} # show_motd_warning
get_random_mac ()
{
local prefixes=("02" "06" "0A" "0E")
local random=$(shuf -i 0-3 -n 1)
MACADDR=$(printf ${prefixes[$random]}':%02X:%02X:%02X:%02X:%02X\n' $[RANDOM%256] $[RANDOM%256] $[RANDOM%256] $[RANDOM%256] $[RANDOM%256])
}
# set fixed IP address from first randomly assigned one. If nothing is detected, generate one.
set_fixed_mac ()
{
if [ -n "$(command -v nmcli)" ]; then
CONNECTION="$(nmcli -f UUID,ACTIVE,DEVICE,TYPE connection show --active | tail -n1)"
UUID=$(awk -F" " '/ethernet/ {print $1}' <<< "${CONNECTION}")
DEVNAME=$(awk -F" " '/ethernet/ {print $3}' <<< "${CONNECTION}")
else
DEVNAME=eth0
fi
MACADDR=$(/sbin/ip link | grep -A1 ${DEVNAME} | awk -F" " '/ether / {print $2}')
[[ -z $MACADDR ]] && get_random_mac
if [[ -n "$(command -v nmcli)" && -n $UUID ]]; then
nmcli connection modify "$UUID" ethernet.cloned-mac-address "$MACADDR"
nmcli connection modify "$UUID" -ethernet.mac-address ""
nmcli connection down "$UUID" >/dev/null 2>&1
nmcli connection up "$UUID" >/dev/null 2>&1
elif [[ -f /etc/systemd/network/$DEVNAME.network ]]; then
if ! grep '^ *MACAddress=' /etc/systemd/network/$DEVNAME.network > /dev/null; then
sed -i "s/#MACAddress=/MACAddress=$MACADDR/g" /etc/systemd/network/$DEVNAME.network
fi
fi
return 0
} # set fixed mac to the 1st active network adapter

View File

@@ -0,0 +1,549 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
# read distribution status
# shellcheck source=/dev/null
[[ -f /etc/lsb-release ]] && . /etc/lsb-release
[[ -f /etc/os-release ]] && . /etc/os-release
[[ -z "$DISTRIB_CODENAME" ]] && DISTRIB_CODENAME="${VERSION_CODENAME}"
[[ -n "$DISTRIB_CODENAME" && -f /etc/armbian-distribution-status ]] && DISTRIBUTION_STATUS=$(grep "$DISTRIB_CODENAME" /etc/armbian-distribution-status | cut -d"=" -f2)
. /etc/armbian-release
check_abort()
{
echo -e "\nDisabling user account creation procedure\n"
rm -f /root/.not_logged_in_yet
if [[ ${USER_SHELL} == zsh ]]; then
printf "\nYou selected \e[0;91mZSH\x1B[0m as your default shell. If you want to use it right away, please logout and login! \n\n"
fi
trap - INT
exit 0
}
read_password()
{
unset password
unset charcount
prompt="$1 password: "
stty -echo
charcount=0
while IFS= read -p "$prompt" -r -s -n 1 char
do
if [[ $char == $'\0' ]]
then
break
fi
# Handle backspace
if [[ $char == $'\177' ]]
then
if [ $charcount -gt 0 ]
then
charcount=$((charcount-1))
prompt=$'\b \b'
password="${password%?}"
else
prompt=''
fi
else
charcount=$((charcount+1))
prompt='*'
password+="$char"
fi
done
stty echo
}
set_shell()
{
readarray -t optionsAudits <<<"$(grep "zsh\|/bash" /etc/shells | sed 's/\/bin\///g' | sed 's/\/usr//g' | uniq)"
USER_SHELL="bash"
if [[ "${#optionsAudits[@]}" -gt 1 ]]; then
while :
do
while [[ ! "${reply}" =~ ^(1|2)$ ]]; do
i=1
echo -e "\nChoose default system command shell:\n"
for o in "${optionsAudits[@]}"; do
echo "$i) $o"
(( i++ )) || true
done
read -r reply
done
case $reply in
"1"|"${optionsAudits[0]}") USER_SHELL="${optionsAudits[0]}"; break;;
"2"|"${optionsAudits[1]}") USER_SHELL="${optionsAudits[1]}"; break;;
*) USER_SHELL="${optionsAudits[0]}"; break;;
esac
done
fi
SHELL_PATH=$(grep "/$USER_SHELL$" /etc/shells | tail -1)
chsh -s "$(grep -iF "/$USER_SHELL" /etc/shells | tail -1)"
echo -e "\nShell: \x1B[92m${USER_SHELL^^}\x1B[0m"
# change shell for future users
sed -i "s|^SHELL=.*|SHELL=${SHELL_PATH}|" /etc/default/useradd
sed -i "s|^DSHELL=.*|DSHELL=${SHELL_PATH}|" /etc/adduser.conf
}
set_timezone_and_locales()
{
# Grab this machine's public IP address
PUBLIC_IP=$(curl --max-time 5 -s https://ipinfo.io/ip)
# Check if we have wireless adaptor
WIFI_DEVICE=$(LC_ALL=C nmcli dev status | grep " wifi " 2>/dev/null)
if [ -z "$PUBLIC_IP" ]; then
# ask for connecting to wireless if wifi device is found
if [[ -n "$WIFI_DEVICE" ]]; then
echo -e "Internet connection was \x1B[91mnot detected\x1B[0m."
echo ""
unset response
while [[ ! "${response}" =~ ^(Y|y|N|n)$ ]]; do
read -r -p "Connect via wireless? [Y/n] " response
response=${response:-Y}
echo "$response"
done
if [[ "${response}" =~ ^(Y|y)$ ]]; then
nmtui-connect
fi
echo ""
fi
fi
# Grab IP once again if not found
[[ -z "$PUBLIC_IP" && -n "$WIFI_DEVICE" ]] && PUBLIC_IP=$(curl --max-time 5 -s https://ipinfo.io/ip)
# Call the geolocation API and capture the output
RES=$(
curl --max-time 5 -s "http://ipwhois.app/json/${PUBLIC_IP}" | \
jq '.timezone, .country, .country_code' | \
while read -r TIMEZONE; do
read -r COUNTRY
echo "${TIMEZONE},${COUNTRY},${COUNTRYCODE}" | tr --delete '"\n'
done
)
TZDATA=$(echo "${RES}" | cut -d"," -f1)
CCODE=$(echo "${RES}" | cut -d"," -f3 | xargs)
echo -e "Detected timezone: \x1B[92m$TZDATA\x1B[0m"
echo ""
unset response
while [[ ! "${response}" =~ ^(Y|y|N|n)$ ]]; do
read -r -p "Set user language based on your location? [Y/n] " response
response=${response:-Y}
echo "$response"
done
# change it only if we have a match and if we agree
if [[ "${response}" =~ ^(N|n)$ ]]; then
unset CCODE TZDATA
fi
LOCALES=$(grep territory /usr/share/i18n/locales/* | grep _"$CCODE" | cut -d ":" -f 1 | cut -d "/" -f 6 | \
xargs -I{} grep {} /usr/share/i18n/SUPPORTED | grep "\.UTF-8" | cut -d " " -f 1)
# UTF8 is not present everywhere so check again in case it returns empty value
[[ -z "$LOCALES" ]] && LOCALES=$(grep territory /usr/share/i18n/locales/* | grep _"$CCODE" | cut -d ":" -f 1 | cut -d "/" -f 6 | \
xargs -I{} grep {} /usr/share/i18n/SUPPORTED | cut -d " " -f 1)
readarray -t options <<<"${LOCALES}"
# when having more locales, prompt for choosing one
if [[ "${#options[@]}" -gt 1 ]]; then
options+=("Skip generating locales")
echo -e "\nAt your location, more locales are possible:\n"
PS3='Please enter your choice:'
select opt in "${options[@]}"
do
if [[ " ${options[*]} " == *" ${opt} "* ]]; then
LOCALES=${opt}
break
fi
done
fi
if [[ "${LOCALES}" != *Skip* ]]; then
# if TZDATA was not detected, we need to select one
if [[ -z ${TZDATA} ]]; then
TZDATA=$(tzselect | tail -1)
fi
timedatectl set-timezone "${TZDATA}"
dpkg-reconfigure --frontend=noninteractive tzdata > /dev/null 2>&1
# generate locales
echo ""
sed -i 's/# '"${LOCALES}"'/'"${LOCALES}"'/' /etc/locale.gen
echo -e "Generating locales: \x1B[92m${LOCALES}\x1B[0m"
locale-gen "${LOCALES}" > /dev/null 2>&1
# setting detected locales only for user
{
echo "export LC_ALL=$LOCALES"
echo "export LANG=$LOCALES"
echo "export LANGUAGE=$LOCALES"
} >> /home/"$RealUserName"/.bashrc
{
echo "export LC_ALL=$LOCALES"
echo "export LANG=$LOCALES"
echo "export LANGUAGE=$LOCALES"
} >> /home/"$RealUserName"/.xsessionrc
fi
}
add_profile_sync_settings()
{
/usr/bin/psd >/dev/null 2>&1
config_file="${HOME}/.config/psd/psd.conf"
if [ -f "${config_file}" ]; then
# test for overlayfs
sed -i 's/#USE_OVERLAYFS=.*/USE_OVERLAYFS="yes"/' "${config_file}"
case $(/usr/bin/psd p 2>/dev/null | grep Overlayfs) in
*active*)
echo -e "\nConfigured profile sync daemon with overlayfs."
;;
*)
echo -e "\nConfigured profile sync daemon."
sed -i 's/USE_OVERLAYFS="yes"/#USE_OVERLAYFS="no"/' "${config_file}"
;;
esac
fi
systemctl --user enable psd.service >/dev/null 2>&1
systemctl --user start psd.service >/dev/null 2>&1
}
add_user()
{
read -r -t 0 _
REPEATS=3
while [ -f "/root/.not_logged_in_yet" ]; do
echo -e "\nPlease provide a username (eg. your first name): \c"
read -r -e username
if ! grep '^[a-zA-Z][a-zA-Z0-9]*$' <<< "$username" > /dev/null ; then
echo -e "\n\x1B[91mError\x1B[0m: illegal characters in username"
return
fi
RealUserName="$(echo "$username" | tr '[:upper:]' '[:lower:]' | tr -d -c '[:alnum:]')"
[ -z "$RealUserName" ] && return
if ! id "$RealUserName" >/dev/null 2>&1; then break; else echo -e "Username \e[0;31m$RealUserName\x1B[0m already exists on the system."; fi
done
while [ -f "/root/.not_logged_in_yet" ]; do
read_password "Create user ($username)"
first_input="$password"
echo ""
read_password "Repeat user ($username)"
second_input="$password"
echo ""
if [[ "$first_input" == "$second_input" ]]; then
# minimal images might not have this
if command -v cracklib-check >/dev/null 2>&1; then
result="$(cracklib-check <<<"$password")"
okay="$(awk -F': ' '{ print $2}' <<<"$result")"
if [[ "$okay" != "OK" ]]; then
echo -e "\n\e[0;31mWarning:\x1B[0m Weak password, $okay \b!"
fi
fi
echo -e ""
read -r -e -p "Please provide your real name: " -i "${RealUserName^}" RealName
adduser --quiet --disabled-password --home /home/"$RealUserName" --gecos "$RealName" "$RealUserName"
(echo "$first_input";echo "$second_input";) | passwd "$RealUserName" >/dev/null 2>&1
for additionalgroup in sudo netdev audio video disk tty users games dialout plugdev input bluetooth systemd-journal ssh; do
usermod -aG "${additionalgroup}" "${RealUserName}" 2>/dev/null
done
# fix for gksu in Xenial
touch /home/"$RealUserName"/.Xauthority
chown "$RealUserName":"$RealUserName" /home/"$RealUserName"/.Xauthority
RealName="$(awk -F":" "/^${RealUserName}:/ {print \$5}" </etc/passwd | cut -d',' -f1)"
[ -z "$RealName" ] && RealName="$RealUserName"
echo -e "\nDear \e[0;92m${RealName}\x1B[0m, your account \e[0;92m${RealUserName}\x1B[0m has been created and is sudo enabled."
echo -e "Please use this account for your daily work from now on.\n"
rm -f /root/.not_logged_in_yet
chmod +x /etc/update-motd.d/*
# set up profile sync daemon on desktop systems
if command -v psd >/dev/null 2>&1; then
echo -e "${RealUserName} ALL=(ALL) NOPASSWD: /usr/bin/psd-overlay-helper" >> /etc/sudoers
touch /home/"${RealUserName}"/.activate_psd
chown "$RealUserName":"$RealUserName" /home/"${RealUserName}"/.activate_psd
fi
break
elif [[ -n $password ]]; then
echo -e "Rejected - \e[0;31mpasswords do not match.\x1B[0m Try again [${REPEATS}]."
REPEATS=$((REPEATS - 1))
fi
[[ "$REPEATS" -eq 0 ]] && logout
done
}
if [[ -f /root/.not_logged_in_yet && -n $(tty) ]]; then
# disable autologin
rm -f /etc/systemd/system/getty@.service.d/override.conf
rm -f /etc/systemd/system/serial-getty@.service.d/override.conf
systemctl daemon-reload
# detect display manager
desktop_lightdm=$(dpkg-query -W -f='${db:Status-Abbrev}\n' lightdm 2>/dev/null)
desktop_gdm3=$(dpkg-query -W -f='${db:Status-Abbrev}\n' gdm3 2>/dev/null)
echo -e "\nWaiting for system to finish booting ..."
systemctl is-system-running --wait >/dev/null
# enable hiDPI support
if [[ "$(cut -d, -f1 < /sys/class/graphics/fb0/virtual_size 2> /dev/null)" -gt 1920 ]]; then
# lightdm
[[ -f /etc/lightdm/slick-greeter.conf ]] && echo "enable-hidpi = on" >> /etc/lightdm/slick-greeter.conf
# xfce
[[ -f /etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml ]] && sed -i 's|<property name="WindowScalingFactor" type="int" value=".*|<property name="WindowScalingFactor" type="int" value="2">|g' /etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml
setfont /usr/share/consolefonts/Uni3-TerminusBold32x16.psf.gz
fi
clear
echo -e "Welcome to \e[1m\e[97mARMBIAN\x1B[0m! \n"
echo -e "Documentation: \e[1m\e[92mhttps://docs.armbian.com\x1B[0m | Community: \e[1m\e[92mhttps://forum.armbian.com\x1B[0m\n"
GET_IP=$(bash /etc/update-motd.d/30-armbian-sysinfo | grep IP | sed "s/.*IP://" | sed 's/^[ \t]*//')
[[ -n "$GET_IP" ]] && echo -e "IP address: $GET_IP\n"
trap '' 2
REPEATS=3
while [ -f "/root/.not_logged_in_yet" ]; do
read_password "Create root"
# only allow one login. Once you enter root password, kill others.
loginfrom=$(who am i | awk '{print $2}')
who -la | grep root | grep -v "$loginfrom" | awk '{print $7}' | xargs --no-run-if-empty kill -9
first_input="$password"
echo ""
read_password "Repeat root"
second_input="$password"
echo ""
if [[ "$first_input" == "$second_input" ]]; then
# minimal might not have this
if command -v cracklib-check >/dev/null 2>&1; then
result="$(cracklib-check <<<"$password")"
okay="$(awk -F': ' '{ print $2}' <<<"$result")"
if [[ "$okay" != "OK" ]]; then
echo -e "\n\e[0;31mWarning:\x1B[0m Weak password, $okay \b!"
fi
fi
(echo "$first_input";echo "$second_input";) | passwd root >/dev/null 2>&1
break
elif [[ -n $password ]]; then
echo -e "Rejected - \e[0;31mpasswords do not match.\x1B[0m Try again [${REPEATS}]."
REPEATS=$((REPEATS - 1))
fi
[[ "$REPEATS" -eq 0 ]] && exit
done
trap - INT TERM EXIT
# display support status
if [ "$IMAGE_TYPE" != "nightly" ]; then
if [[ "$BRANCH" == "edge" ]]; then
echo -e "\nSupport status: \e[0;31mcommunity support\x1B[0m (edge kernel branch)"
elif [[ "$DISTRIBUTION_STATUS" != "supported" ]]; then
echo -e "\nSupport status: \e[0;31mcommunity support\x1B[0m (unsupported userspace)"
elif [[ "$BOARD_TYPE" != "conf" ]]; then
echo -e "\nSupport status: \e[0;31mcommunity support\x1B[0m (looking for a dedicated maintainer)"
fi
else
echo -e "\e[0;31m\nWARNING!\x1B[0m\n\nYou are using an \e[0;31mautomated build\x1B[0m meant only for developers to provide"
echo -e "constructive feedback to improve build system, OS settings or UX.\n"
echo -e "If this does not apply to you, \e[0;31mSTOP NOW!\x1B[0m Especially don't use this "
echo -e "image for production since things might not work as expected or at "
echo -e "all. They may break anytime with next update."
fi
# ask user to select shell
trap '' 2
set_shell
trap - INT TERM EXIT
trap check_abort INT
while [ -f "/root/.not_logged_in_yet" ]; do
echo -e "\nCreating a new user account. Press <Ctrl-C> to abort"
[ -n "$desktop_lightdm" ] && echo -e "\n\e[0;31mDesktop environment will not be enabled if you abort the new user creation\x1B[0m"
add_user
done
trap - INT TERM EXIT
# ask user to select automated locales or not
trap '' 2
set_timezone_and_locales
trap - INT TERM EXIT
if [[ ${USER_SHELL} == zsh ]]; then
printf "\nYou selected \e[0;91mZSH\x1B[0m as your default shell. If you want to use it right away, please logout and login! \n\n"
fi
# check whether desktop environment has to be considered
if [ -n "$desktop_lightdm" ] && [ -n "$RealName" ] ; then
# 1st run goes without login
mkdir -p /etc/lightdm/lightdm.conf.d
cat <<-EOF > /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
[Seat:*]
autologin-user=$RealUserName
autologin-user-timeout=0
user-session=xfce
EOF
# select gnome session (has to be first or it breaks budgie/cinnamon desktop autologin and user-session)
[[ -x $(command -v gnome-session) ]] && sed -i "s/user-session.*/user-session=ubuntu/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v gnome-session) ]] && sed -i "s/user-session.*/user-session=ubuntu/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select awesome session
[[ -x $(command -v awesome) ]] && sed -i "s/user-session.*/user-session=awesome/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v awesome) ]] && sed -i "s/user-session.*/user-session=awesome/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select budgie session
[[ -x $(command -v budgie-desktop) ]] && sed -i "s/user-session.*/user-session=budgie-desktop/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v budgie-desktop) ]] && sed -i "s/user-session.*/user-session=budgie-desktop/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select cinnamon session
[[ -x $(command -v cinnamon) ]] && sed -i "s/user-session.*/user-session=cinnamon/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v cinnamon) ]] && sed -i "s/user-session.*/user-session=cinnamon/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select deepin session
[[ -x $(command -v deepin-wm) ]] && sed -i "s/user-session.*/user-session=deepin/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v deepin-wm) ]] && sed -i "s/user-session.*/user-session=deepin/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select ice-wm session
[[ -x $(command -v icewm-session) ]] && sed -i "s/user-session.*/user-session=icewm-session/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v icewm-session) ]] && sed -i "s/user-session.*/user-session=icewm-session/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select i3 session
[[ -x $(command -v i3) ]] && sed -i "s/user-session.*/user-session=i3/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v i3) ]] && sed -i "s/user-session.*/user-session=i3/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select lxde session
[[ -x $(command -v startlxde) ]] && sed -i "s/user-session.*/user-session=LXDE/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v startlxde) ]] && sed -i "s/user-session.*/user-session=LXDE/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select lxqt session
[[ -x $(command -v startlxqt) ]] && sed -i "s/user-session.*/user-session=lxqt/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v startlxqt) ]] && sed -i "s/user-session.*/user-session=lxqt/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select mate session
[[ -x $(command -v mate-wm) ]] && sed -i "s/user-session.*/user-session=mate/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v mate-wm) ]] && sed -i "s/user-session.*/user-session=mate/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select plasma wayland session
[[ -x $(command -v plasmashell) ]] && sed -i "s/user-session.*/user-session=plasmawayland/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v plasmashell) ]] && sed -i "s/user-session.*/user-session=plasmawayland/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select sway wayland session
[[ -x $(command -v sway) ]] && sed -i "s/user-session.*/user-session=sway/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v sway) ]] && sed -i "s/user-session.*/user-session=sway/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
# select xmonad session
[[ -x $(command -v xmonad) ]] && sed -i "s/user-session.*/user-session=xmonad/" /etc/lightdm/lightdm.conf.d/11-armbian.conf
[[ -x $(command -v xmonad) ]] && sed -i "s/user-session.*/user-session=xmonad/" /etc/lightdm/lightdm.conf.d/22-armbian-autologin.conf
ln -sf /lib/systemd/system/lightdm.service /etc/systemd/system/display-manager.service
if [[ -f /var/run/resize2fs-reboot ]]; then
# Let the user reboot now otherwise start desktop environment
printf "\n\n\e[0;91mWarning: a reboot is needed to finish resizing the filesystem \x1B[0m \n"
printf "\e[0;91mPlease reboot the system now \x1B[0m \n\n"
else
echo -e "\n\e[1m\e[39mNow starting desktop environment...\x1B[0m\n"
sleep 1
service lightdm start 2>/dev/null
if [ -f /root/.desktop_autologin ]; then
rm /root/.desktop_autologin
else
systemctl -q enable armbian-disable-autologin.timer
systemctl start armbian-disable-autologin.timer
fi
# logout if logged at console
who -la | grep root | grep -q tty1 && exit 1
fi
elif [ -n "$desktop_gdm3" ] && [ -n "$RealName" ] ; then
# 1st run goes without login
mkdir -p /etc/gdm3
cat <<-EOF > /etc/gdm3/custom.conf
[daemon]
AutomaticLoginEnable = true
AutomaticLogin = $RealUserName
EOF
ln -sf /lib/systemd/system/gdm3.service /etc/systemd/system/display-manager.service
if [[ -f /var/run/resize2fs-reboot ]]; then
# Let the user reboot now otherwise start desktop environment
printf "\n\n\e[0;91mWarning: a reboot is needed to finish resizing the filesystem \x1B[0m \n"
printf "\e[0;91mPlease reboot the system now \x1B[0m \n\n"
else
echo -e "\n\e[1m\e[39mNow starting desktop environment...\x1B[0m\n"
sleep 1
service gdm3 start 2>/dev/null
if [ -f /root/.desktop_autologin ]; then
rm /root/.desktop_autologin
else
(sleep 20; sed -i "s/AutomaticLoginEnable.*/AutomaticLoginEnable = false/" /etc/gdm3/custom.conf) &
fi
# logout if logged at console
who -la | grep root | grep -q tty1 && exit 1
fi
else
# Display reboot recommendation if necessary
if [[ -f /var/run/resize2fs-reboot ]]; then
printf "\n\n\e[0;91mWarning: a reboot is needed to finish resizing the filesystem \x1B[0m \n"
printf "\e[0;91mPlease reboot the system now \x1B[0m \n\n"
fi
fi
fi

View File

@@ -0,0 +1,137 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
. /etc/armbian-release
. /etc/os-release
. /lib/init/vars.sh
. /lib/lsb/init-functions
. /usr/lib/armbian/armbian-common
case "$1" in
start)
# read number of cores needed below
cpu_cores=$(grep -c '^processor' /proc/cpuinfo | sed 's/^0$/1/')
# adjust custom htop initial configuration based on CPU count https://github.com/avafinger/htop-2.1.1_enhanced-version
right_meters="Hostname Tasks LoadAverage DiskIO NetworkIO Uptime Systemd CpuFreq"
right_meter_modes="2 2 2 2 2 2 2 2"
sed -i 's/header_margin=.*/header_margin=1/g' /etc/skel/.config/htop/htoprc
sed -i 's/left_meters=.*/left_meters=AllCPUs Memory Zram Swap CpuTemp/g' /etc/skel/.config/htop/htoprc
sed -i 's/left_meter_modes=.*/left_meter_modes=1 1 1 1 2/g' /etc/skel/.config/htop/htoprc
sed -i "s/right_meters=.*/right_meters=$right_meters/g" /etc/skel/.config/htop/htoprc
sed -i "s/right_meter_modes=.*/right_meter_modes=$right_meter_modes/g" /etc/skel/.config/htop/htoprc
# copy predefined settings for root user
cp -R /etc/skel/.config /root/
# Run a q&d benchmark to be able to identify cards way too slow easily
echo -e "\n### quick iozone test:$(cd /root; iozone -e -I -a -s 1M -r 4k -i 0 -i 1 -i 2 | grep '^ 1024' | sed 's/ 1024 //')" >> $Log
# Bluetooth tweaks
case ${BOARD} in
cubietruck)
systemctl enable brcm40183-patch && service brcm40183-patch start
;;
bananapim2zero|bananapim2plus|nanopiair|nanopim1plus|orangepizeroplus2*|orangepiwin|nanopineoplus2|nanopik2)
update-rc.d ap6212-bluetooth defaults
;;
esac
# Debian Buster desktop bugfix https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=923289
[[ -d /etc/lightdm ]] && dpkg-reconfigure libgdk-pixbuf2.0-0 && update-mime-database /usr/share/mime
# update console info
setupcon --save
# add unique installation id to the image release file
sed '1s/^/IMAGE_UUID=/' /proc/sys/kernel/random/uuid >> /etc/armbian-image-release
# SSH Keys creation
rm -f /etc/ssh/ssh_host*
read entropy_before </proc/sys/kernel/random/entropy_avail
dpkg-reconfigure openssh-server >/dev/null 2>&1
service sshd restart
read entropy_after </proc/sys/kernel/random/entropy_avail
echo -e "\n### [firstrun] Recreated SSH keys (entropy: ${entropy_before} ${entropy_after})" >>${Log}
# get rid of purple background color in newt apps whiptail, partimage, debconf ... Reverting to Debian look.
[[ -f /etc/newt/palette ]] && sed -e 's/magenta/blue/g' -i /etc/newt/palette
# desktop tweaks - enable show windows content on stronger boards
if [[ ${cpu_cores} -gt 2 && -f /etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml ]]; then
sed -i 's/<property name="box_move" type="bool" value=".*/<property name="box_move" type="bool" value="false"\/>/g' \
/etc/skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml
fi
# randomize mac in armbianEnv.txt
if [[ -f /boot/armbianEnv.txt ]]; then
get_random_mac
sed -i "s/^ethaddr=.*/ethaddr=$MACADDR/" /boot/armbianEnv.txt
get_random_mac
sed -i "s/^eth1addr=.*/eth1addr=$MACADDR/" /boot/armbianEnv.txt
fi
# hardware workarounds per family
case $LINUXFAMILY in
sun7i|sun8i)
# set some mac address for BT
[[ -n $(lsmod | grep -E "dhd|brcmfmac" ) ]] && \
(MACADDR=$(printf '43:29:B1:%02X:%02X:%02X\n' $[RANDOM%256] $[RANDOM%256] $[RANDOM%256]) ; \
sed -i "s/^MAC_ADDR=.*/MAC_ADDR=${MACADDR}/" /etc/default/brcm40183 ;\
sed -i "s/^MAC_ADDR=.*/MAC_ADDR=${MACADDR}/" /etc/default/ap6212 \
echo -e "\n### [firstrun] Use MAC address ${MACADDR} for Bluetooth from now" >>${Log})
case $BOARD_NAME in
"NanoPi Air"|"NanoPi M1 Plus"|"Nanopi Neo Plus 2")
# change serial port for BT on FriendlyELEC H3 boards
sed -i "s/^PORT=.*/PORT=ttyS3/" /etc/default/ap6212
;;
"Orange Pi Zero"|"NanoPi Duo"|"Sunvell R69")
get_random_mac
echo "options xradio_wlan macaddr=${MACADDR}" >/etc/modprobe.d/xradio_wlan.conf
echo -e "\n### [firstrun] Use MAC address ${MACADDR} for Wi-Fi from now" >>${Log}
cd /etc/network/ && ln -sf interfaces.network-manager interfaces
(modprobe -r xradio_wlan && sleep 1 && modprobe xradio_wlan) &
;;
esac
# trigger red or blue LED as user feedback
echo heartbeat >/sys/class/leds/*red*/trigger 2>/dev/null || echo heartbeat >/sys/class/leds/*blue*/trigger 2>/dev/null
;;
mvebu64|mt7623)
# configure/enable/start systemd-networkd
systemctl start systemd-networkd.service
systemctl start systemd-resolved.service
systemctl enable systemd-networkd.service
systemctl enable systemd-resolved.service
ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
systemctl restart systemd-networkd
;;
x86|arm64)
[[ -n "$(dmesg | grep "No NVIDIA GPU found")" ]] && sudo apt-get -y -qq purge nvidia-dkms-510 nvidia-driver-510 nvidia-settings nvidia-common >> /dev/null
;;
*)
esac
# varios temporary hardware workarounds
[[ $LINUXFAMILY == rk3399 || $LINUXFAMILY == rockchip64 ]] && [[ $BOARD != helios64 && $BOARD != khadas-edge ]] && set_fixed_mac
[[ $BRANCH == dev && $LINUXFAMILY == rockchip ]] && set_fixed_mac
[[ $LINUXFAMILY == meson ]] && set_fixed_mac
[[ $LINUXFAMILY == meson64 ]] && set_fixed_mac
systemctl disable armbian-firstrun
exit 0
;;
*)
echo "Usage: $0 start"
exit 0
;;
esac

View File

@@ -0,0 +1,114 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
# Function calculates number of bit in a netmask
#
mask2cidr() {
nbits=0
IFS=.
for dec in $1 ; do
case $dec in
255) let nbits+=8;;
254) let nbits+=7;;
252) let nbits+=6;;
248) let nbits+=5;;
240) let nbits+=4;;
224) let nbits+=3;;
192) let nbits+=2;;
128) let nbits+=1;;
0);;
*) echo "Error: $dec is not recognised"; exit 1
esac
done
echo "$nbits"
}
do_firstrun_automated_user_configuration()
{
#-----------------------------------------------------------------------------
#Notes:
# - See /boot/armbian_first_run.txt for full list of available variables
# - Variable names here must here must match ones in packages/bsp/armbian_first_run.txt.template
#-----------------------------------------------------------------------------
#Config FP
local fp_config='/boot/armbian_first_run.txt'
#-----------------------------------------------------------------------------
#Grab user requested settings
if [[ -f $fp_config ]]; then
# Convert line endings to Unix from Dos
sed -i $'s/\r$//' "$fp_config"
# check syntax
bash -n "$fp_config" || return
# Load vars directly from file
source "$fp_config"
# Obtain backward configuration compatibility
FR_net_static_dns=${FR_net_static_dns// /,}
FR_net_static_mask=$(mask2cidr $FR_net_static_mask)
#-----------------------------------------------------------------------------
# - Remove configuration file
if [[ $FR_general_delete_this_file_after_completion == 1 ]]; then
dd if=/dev/urandom of="$fp_config" bs=16K count=1
sync
rm "$fp_config"
else
mv "$fp_config" "${fp_config}.old"
fi
#-----------------------------------------------------------------------------
# Set Network
if [[ $FR_net_change_defaults == 1 ]]; then
# - Get name of 1st available ethernet and wifi adapter
eth_index="$(nmcli d | grep ethernet | cut -d ' ' -f 1 | head -n 1)"
wlan_index="$(nmcli d | grep wifi | cut -d ' ' -f 1 | head -n 1)"
# for static IP we only append settings
if [[ $FR_net_use_static == 1 ]]; then
local FIXED_IP_SETTINGS="ipv4.method manual ipv4.address ${FR_net_static_ip}/${FR_net_static_mask} ipv4.dns ${FR_net_static_dns} ipv4.gateway ${FR_net_static_gateway}"
fi
if [[ -n $eth_index || -n $wlan_index ]]; then
# delete all current connections
LC_ALL=C nmcli -t -f UUID,DEVICE connection show | awk '{print $1}' | cut -f1 -d":" | xargs nmcli connection delete
# - Wifi enable
if [[ $FR_net_wifi_enabled == 1 ]]; then
#Set wifi country code
iw reg set "$FR_net_wifi_countrycode"
nmcli con add con-name "Armbian wireless" type wifi ifname ${wlan_index} ssid "$FR_net_wifi_ssid" -- wifi-sec.key-mgmt wpa-psk wifi-sec.psk "$FR_net_wifi_key" ${FIXED_IP_SETTINGS}
nmcli con up "Armbian wireless"
#Enable Wlan, disable Eth
FR_net_ethernet_enabled=0
# - Ethernet enable
elif [[ $FR_net_ethernet_enabled == 1 ]]; then
nmcli con add con-name "Armbian ethernet" type ethernet ifname ${eth_index} -- ${FIXED_IP_SETTINGS}
nmcli con up "Armbian ethernet"
#Enable Eth, disable Wlan
FR_net_wifi_enabled=0
fi
fi
fi
fi
} #do_firstrun_automated_user_configuration
do_firstrun_automated_user_configuration
exit 0

View File

@@ -0,0 +1,180 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
# Functions:
#
# prepare_temp_monitoring
# log_hardware_info
# get_flash_information
# check_sd_card_speed
# Read in basic OS image information
. /etc/armbian-release
# and script configuration
. /usr/lib/armbian/armbian-common
prepare_temp_monitoring() {
# still an ugly hack but better do it just once at startup instead of every login
[ -d /etc/armbianmonitor/datasources ] || mkdir -p -m775 /etc/armbianmonitor/datasources
# PMIC check
if [[ -f /sys/power/axp_pmu/pmu/temp ]]; then
ln -fs /sys/power/axp_pmu/pmu/temp /etc/armbianmonitor/datasources/pmictemp
elif [[ -f /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034//temp1_input ]]; then
ln -fs /sys/devices/platform/sunxi-i2c.0/i2c-0/0-0034/temp1_input \
/etc/armbianmonitor/datasources/pmictemp
elif [[ -f /sys/devices/b0170000.i2c/i2c-0/0-0065/atc2603c-hwmon.0/ic_temperature ]]; then
ln -fs /sys/devices/b0170000.i2c/i2c-0/0-0065/atc2603c-hwmon.0/ic_temperature \
/etc/armbianmonitor/datasources/pmictemp
elif [[ -f /sys/class/axppower/ic_temp ]]; then
ln -fs /sys/class/axppower/ic_temp /etc/armbianmonitor/datasources/pmictemp
fi
# SoC temp: check sun7i legacy exception first, then standard path(s)
if [[ -d "/sys/devices/platform/a20-tp-hwmon" ]]; then
# sun7i legacy
ln -fs /sys/devices/platform/a20-tp-hwmon/temp1_input /etc/armbianmonitor/datasources/soctemp
elif [[ -f /sys/class/hwmon/hwmon0/temp1_input && ${BOARDFAMILY} != "mvebu" ]]; then
# usual convention with modern kernels
ln -fs /sys/class/hwmon/hwmon0/temp1_input /etc/armbianmonitor/datasources/soctemp
else
# all other boards/kernels use the same sysfs node except of Actions Semi S500:
[[ ${BOARDFAMILY} == s500 ]] && THERMAL_ZONE="thermal_zone1" || THERMAL_ZONE="thermal_zone0"
ln -fs /sys/devices/virtual/thermal/${THERMAL_ZONE}/temp /etc/armbianmonitor/datasources/soctemp
fi
# Ambient temp
if [[ ${BOARD} == "helios4" && -f /dev/thermal-board/temp1_input ]]; then
ln -fs /dev/thermal-board/temp1_input /etc/armbianmonitor/datasources/ambienttemp
fi
} # prepare_temp_monitoring
log_hardware_info() {
[ -f "/etc/logrotate.d/${0##*/}" ] || \
echo -e "${Log} {\n rotate 12\n weekly\n compress\n missingok\n notifempty\n}" \
> "/etc/logrotate.d/${0##*/}" ; chmod 644 "/etc/logrotate.d/${0##*/}"
CPU_ARCH=$(lscpu | awk '/Architecture/ {print $2}')
DISTRO_ARCH=$(dpkg --print-architecture)
KERNELID=$(uname -r)
echo -e "\n$(date) | ${BOARD_NAME} | ${VERSION} | ${DISTRO_ARCH} | ${CPU_ARCH} | ${KERNELID}" >>${Log}
chmod 644 ${Log}
echo -e "\n### dmesg:\n" >>${Log}
dmesg >>${Log}
echo -e "\n### armbian-release:\n" >>${Log}
cat /etc/armbian-release >>${Log}
echo -e "\n### boot environment:\n" >>${Log}
cat /boot/armbianEnv.txt >>${Log} 2>/dev/null || grep -v "^#" /boot/boot.ini | sed '/^\s*$/d' >>${Log}
echo -e "\n### lsusb:\n" >>${Log}
lsusb 2>/dev/null >>${Log}
echo -e "\n### lscpu:\n" >>${Log}
lscpu >>${Log}
echo -e "\n### cpuinfo:\n" >>${Log}
cat /proc/cpuinfo >>${Log}
echo -e "\n### meminfo:\n" >>${Log}
cat /proc/meminfo >>${Log}
echo -e "\n### virtual memory:\n" >>${Log}
for sysfsnode in /proc/sys/vm/* ; do sysctl $(echo ${sysfsnode} | sed 's|/proc/sys/vm/|vm.|'); done >>${Log}
if [ -x /sbin/ip ]; then
echo -e "\n### ip addr:\n" >>${Log}
/sbin/ip r s >>${Log} ; /sbin/ip a >>${Log}
echo " " >>${Log}
else
echo -e "\n### ifconfig:\n" >>${Log}
ifconfig >>${Log}
fi
echo -e "### partitions:\n" >>${Log}
grep -v " ram" /proc/partitions >>${Log}
echo -e "\n### df:\n" >>${Log}
df -h | grep -E '^udev|^tmpfs|^/dev/|log2ram|folder2ram' >>${Log}
command -v zpool >/dev/null 2>&1 && echo -e "\n### zpools:\n\n$(zpool list)\n\n### zfs datasets:\n\n$(zfs list)" >>${Log}
echo -e "\n### lsblk:\n" >>${Log}
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,UUID | grep -v "SWAP" >>${Log}
command -v zramctl >/dev/null 2>&1 && echo -e "\n### zramctl:\n\n$(zramctl)" >>${Log}
echo -e "\n### mtab:\n" >>${Log}
grep -E '^/dev/|\ zfs\ ' /etc/mtab | grep -Ev "log2ram|folder2ram" | sort >>${Log}
[[ -e /boot/script.bin ]] && echo -e "\n### /boot/script.bin --> $(readlink /boot/script.bin)" >>${Log}
get_flash_information >>${Log}
echo -e "\n### Boot system health:\n" >>${Log}
armbianmonitor -s | grep -E "^Time|^[0-9]" >>${Log}
} # log_hardware_info
get_flash_information() {
# http://www.bunniestudios.com/blog/?page_id=1022
find /sys -name oemid | while read Device ; do
DeviceNode="${Device%/*}"
DeviceName="${DeviceNode##*/}"
echo -e "\n### ${DeviceName} info:\n"
find "${DeviceNode}" -maxdepth 1 -type f | while read ; do
NodeName="${REPLY##*/}"
echo -e "$(printf "%20s" ${NodeName}): $(cat "${DeviceNode}/${NodeName}" | tr '\n' " ")"
done
done
} # get_flash_information
check_sd_card_speed() {
# function that checks on 3rd boot whether firstrun script made a quick benchmark
# and displays a motd warning when _random_ I/O is below some tresholds.
if [ -f /var/log/armbian-hardware-monitor.log ]; then
RebootCount=$(grep -c '^### df:' /var/log/armbian-hardware-monitor.log)
if [ ${RebootCount} -eq 2 ]; then
# check whether iozone data has been collected
IozoneResults="$(awk -F" " '/^### quick iozone test/ {print $10"\t"$11}' </var/log/armbian-hardware-monitor.log)"
if [ "X${IozoneResults}" != "X" ]; then
set ${IozoneResults}
Readspeed=$1
Writespeed=$2
if [ ${Readspeed} -lt 500 -o ${Writespeed} -lt 250 ]; then
show_motd_warning "Your SD card seems to be very slow. Please check performance using armbianmonitor -c"
fi
fi
fi
fi
} # check_sd_card_speed
case $1 in
*start*)
# check sd card speed once on 3rd boot too warn for too slow media
check_sd_card_speed &
# prepare correct temperature readouts
prepare_temp_monitoring &
# log hardware id to file, write log
echo $BOARD_NAME >/var/run/machine.id # we should leave this, maybe users depend on it
if [ $? -ne 0 ]; then
# most probably readonly fs. We'll try to warn the user.
show_motd_warning "It seems the rootfs is readonly at the moment. Please check your SD card for errors"
fi
# check whether auto detection override exists and if true use this for machine.id
[ -f /root/.machine.id ] && cat /root/.machine.id >/var/run/machine.id
log_hardware_info &
;;
*stop*)
case ${BOARDFAMILY} in
sun?i)
# redefine green led to blink until shutdown, try to switch OTG port to host
(echo heartbeat >/sys/class/leds/*green*/trigger) 2>/dev/null
echo 0 > /sys/bus/platform/devices/sunxi_usb_udc/otg_role 2>/dev/null
;;
esac
# some kernel modules are known to crash the kernel on shutdown (an example
# is the mass storage gadget module at least on sun7i). We try to unload as
# much modules as possible to minimize such situations:
/sbin/modprobe -r $(cut -f1 -d' ' </proc/modules)
# shutdown logging
if [ -f /var/log.hdd/armbian-hardware-monitor.log ]; then
echo -e "\n### shutdown:\n\n$(iostat -p zram0)\n\n$(vmstat -w)\n\n$(free -h)\n\n$(dmesg | tail -n 100)" >>/var/log.hdd/armbian-hardware-monitor.log
else
echo -e "\n### shutdown:\n\n$(iostat -p zram0)\n\n$(vmstat -w)\n\n$(free -h)\n\n$(dmesg | tail -n 100)" >>/var/log/armbian-hardware-monitor.log
fi
sync
;;
esac

View File

@@ -0,0 +1,453 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
# Functions:
#
# set_io_scheduler
# prepare_board
# add_usb_storage_quirks
# Read in basic OS image information
. /etc/armbian-release
# and script configuration
. /usr/lib/armbian/armbian-common
# set audio
. /usr/lib/armbian/armbian-audio-config
set_io_scheduler() {
# Convert kernel version to integer
KERNELID=$(uname -r | awk -F'.' '{print ($1 * 100) + $2}')
for i in $(lsblk -idn -o NAME | grep -v zram); do
read ROTATE < /sys/block/$i/queue/rotational
case ${ROTATE} in
1) # mechanical drives
[[ $KERNELID -lt 420 ]] && sched=cfq || sched=bfq
;;
0) # flash based
[[ $KERNELID -lt 420 ]] && sched=noop || sched=none
;;
*)
continue
;;
esac
echo $sched > /sys/block/$i/queue/scheduler
echo -e "[\e[0;32m ok \x1B[0m] Setting $sched I/O scheduler for $i"
done
} # set_io_scheduler
prepare_board() {
CheckDevice=$(for i in /var/log /var /; do findmnt -n -o SOURCE $i && break; done)
# adjust logrotate configs
if [[ "${CheckDevice}" == *"/dev/zram"* || "${CheckDevice}" == "armbian-ramlog" ]]; then
for ConfigFile in /etc/logrotate.d/*; do sed -i -e "s/\/var\/log\//\/var\/log.hdd\//g" "${ConfigFile}"; done
sed -i "s/\/var\/log\//\/var\/log.hdd\//g" /etc/logrotate.conf
else
for ConfigFile in /etc/logrotate.d/*; do sed -i -e "s/\/var\/log.hdd\//\/var\/log\//g" "${ConfigFile}"; done
sed -i "s/\/var\/log.hdd\//\/var\/log\//g" /etc/logrotate.conf
fi
# unlock cpuinfo_cur_freq to be accesible by a normal user
prefix="/sys/devices/system/cpu/cpufreq"
for f in $(ls -1 $prefix 2> /dev/null); do
[[ -f $prefix/$f/cpuinfo_cur_freq ]] && chmod +r $prefix/$f/cpuinfo_cur_freq 2> /dev/null
done
# older kernels
prefix="/sys/devices/system/cpu/cpu0/cpufreq/"
[[ -f $prefix/cpuinfo_cur_freq ]] && chmod +r $prefix/cpuinfo_cur_freq 2> /dev/null
# enable compression where not exists
find /etc/logrotate.d/. -type f | xargs grep -H -c 'compress' | grep 0$ | cut -d':' -f1 | xargs -r -L1 sed -i '/{/ a compress'
sed -i "s/#compress/compress/" /etc/logrotate.conf
# tweak ondemand cpufreq governor settings to increase cpufreq with IO load
grep -q ondemand /etc/default/cpufrequtils
if [ $? -eq 0 ]; then
echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
case ${BOARDFAMILY} in
station* | media | rockchip-rk3588)
prefix="/sys/devices/system/cpu"
CPUFreqPolicies=($(ls -d ${prefix}/cpufreq/policy? | sed 's/freq\/policy//'))
if [ ${#CPUFreqPolicies[@]} -eq 1 -a -d "${prefix}/cpufreq" ]; then
# if there's just a single cpufreq policy ondemand sysfs entries differ
CPUFreqPolicies=${prefix}
fi
for i in "${CPUFreqPolicies[@]}"; do
affected_cpu=$(tr -d -c '[:digit:]' <<< ${i})
echo ondemand > ${prefix}/cpu${affected_cpu:-0}/cpufreq/scaling_governor
echo 1 > ${i}/cpufreq/ondemand/io_is_busy
echo 25 > ${i}/cpufreq/ondemand/up_threshold
echo 10 > ${i}/cpufreq/ondemand/sampling_down_factor
echo 200000 > ${i}/cpufreq/ondemand/sampling_rate
done
;;
*)
cd /sys/devices/system/cpu
for i in cpufreq/ondemand cpu0/cpufreq/ondemand cpu4/cpufreq/ondemand; do
if [ -d $i ]; then
echo 1 > ${i}/io_is_busy
echo 25 > ${i}/up_threshold
echo 10 > ${i}/sampling_down_factor
echo 200000 > ${i}/sampling_rate
fi
done
;;
esac
fi
# IRQ distribution based on $BOARDFAMILY and/or $BOARD_NAME
case ${BOARD} in
rockpro64 | renegade-elite | pinebook-pro | station-p1)
BOARDFAMILY=rk3399
;;
esac
case ${BOARDFAMILY} in
cubox | udoo*) # i.MX6 boards: send Ethernet to cpu3, MMC to cpu1/cpu2 (when available)
echo 2 > /proc/irq/$(awk -F":" "/mmc0/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -1)/smp_affinity 2> /dev/null
echo 4 > /proc/irq/$(awk -F":" "/mmc1/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -1)/smp_affinity 2> /dev/null
echo 8 > /proc/irq/$(awk -F":" "/ethernet/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -1)/smp_affinity 2> /dev/null
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
;;
meson-g12b) # S922X/A311D: ODROID N2, possibly VIM3, cpu0/cpu1 are the little ones
# MMC on cpu1, USB3 on cpu2, Ethernet on cpu3, rdma on cpu4, vsync on cpu5
for i in $(awk -F':' '/mmc/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 1 > /proc/irq/$i/smp_affinity_list
done
echo 2 > /proc/irq/$(awk -F":" "/xhci-hcd/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 3 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
# mainline kernel might lack those
[[ -n $(grep "rdma" /proc/interrupts) ]] && echo 4 > /proc/irq/$(awk -F":" "/rdma/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
[[ -n $(grep "osd-vsync" /proc/interrupts) ]] && echo 5 > /proc/irq/$(awk -F":" "/ osd-vsync/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
# test fan on Odroid N2 plus - spin it up shortly
if [[ -f /sys/devices/virtual/thermal/thermal_zone0/trip_point_4_temp ]]; then
echo 20000 > /sys/devices/virtual/thermal/thermal_zone0/trip_point_4_temp
sleep 1
echo 65000 > /sys/devices/virtual/thermal/thermal_zone0/trip_point_4_temp
fi
;;
mvebu*) # Clearfog/Turris/Helios4/Espressobin: Send network IRQs to cpu1 on both kernels
for i in $(awk -F':' '/mwlwifi|mvneta|eth0/{print $1}' /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
;;
odroidc1) # ODROID-C0/C1/C1+
echo 1 > /proc/irq/$(awk -F":" "/usb1/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
for i in $(awk -F':' '/Mali_/{print $1}' < /proc/interrupts | sed 's/\ //g'); do echo 1 > /proc/irq/${i}/smp_affinity_list; done
echo 2 > /proc/irq/$(awk -F":" "/usb2/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 3 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
;;
odroidc2 | meson64) # S905/S905X/S912: both kernels: send eth0 to cpu3, mmc/usb2 to cpu2 and usb1 to cpu1
# Basics: http://forum.odroid.com/viewtopic.php?f=115&t=8121#p65777
for i in $(awk -F':' '/sd_emmc|usb2/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 1 > /proc/irq/$i/smp_affinity_list
done
echo 2 > /proc/irq/$(awk -F":" "/usb1/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 3 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
;;
odroidxu4) # ODROID XU3/XU4/HC1/MC1/HC2
echo 2 > /proc/irq/$(awk -F":" "/:usb2/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/:usb3/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 7 > /proc/irq/$(awk -F":" "/:usb5/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 16 > /proc/irq/$(awk -F":" "/dw-mci/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | tail -1)/smp_affinity
echo 32 > /proc/irq/$(awk -F":" "/dw-mci/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -1)/smp_affinity
for i in $(awk -F':' '/11800000.mali/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 64 > /proc/irq/$i/smp_affinity
done
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
;;
rockchip) # RK3288: usb1 on cpu1, usb3 (EHCI) on cpu2, eth0 and GPU on cpu3
echo 2 > /proc/irq/$(awk -F":" "/usb1/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/usb3/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 8 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -n1)/smp_affinity
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
for i in $(awk -F':' '/gpu/{print $1}' /proc/interrupts | sed 's/\ //g'); do
echo 8 > /proc/irq/$i/smp_affinity
done
;;
rk322x) # RK322x: usb otg on cpu1, usb2,3,4 (EHCI), usb5,6,7 (OHCI) on cpu2, eth and GPU on cpu3
echo 2 > /proc/irq/$(awk -F":" "/:usb1/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/:usb2/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/:usb3/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/:usb4/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/:usb5/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/:usb6/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/:usb7/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 8 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -n1)/smp_affinity
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
# Mali in 4.4 kernel
for i in $(awk -F':' '/Mali_/{print $1}' /proc/interrupts | sed 's/\ //g'); do
echo 8 > /proc/irq/$i/smp_affinity
done
# Lima in mainline kernel
echo 8 > /proc/irq/$(awk -F':' '/gp$/{print $1}' /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 8 > /proc/irq/$(awk -F':' '/gpmmu/{print $1}' /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 8 > /proc/irq/$(awk -F':' '/pp0/{print $1}' /proc/interrupts | sed 's/\ //g')/smp_affinity
;;
rockchip64) # Rock64 and Renegade: GPU on cpu1, USB3 on cpu2, Ethernet on cpu3
for i in $(awk -F':' '/Mali/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F":" "/ehci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F":" "/ohci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F":" "/xhci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 4 > /proc/irq/$i/smp_affinity
done
# Wait (up to 5s) until eth0 brought up
for i in {1..5}; do
grep -q "eth0" /proc/interrupts && break
sleep 1
done
echo 8 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
;;
rk3399)
for i in $(awk -F':' '/gpu/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F':' '/dw-mci/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F":" "/ehci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F":" "/ohci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F":" "/xhci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 4 > /proc/irq/$i/smp_affinity
done
# Wait (up to 5s) until eth0 brought up
for i in {1..5}; do
grep -q "eth0" /proc/interrupts && break
sleep 1
done
echo 8 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
for i in $(awk -F':' 'tolower($0) ~ /pcie/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 16 > /proc/irq/$i/smp_affinity
done
# set dmc memory governor to performance with default kernel
if [ -f /sys/bus/platform/drivers/rockchip-dmc/dmc/devfreq/dmc/governor ]; then
echo performance > /sys/bus/platform/drivers/rockchip-dmc/dmc/devfreq/dmc/governor
fi
case ${BOARD_NAME} in
"Helios64")
for i in $(awk -F":" "/xhci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 10 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F":" "/ahci/ {print \$1}" < /proc/interrupts | sed 's/\ //g'); do
echo 30 > /proc/irq/$i/smp_affinity
done
;;
"Pinebook Pro")
echo s2idle > /sys/power/mem_sleep
;;
esac
;;
s500) # Roseapple Pi/LeMaker Guitar: send USB IRQs to cpu1/cpu2, DMA0 to cpu2 and Ethernet + SD card to cpu3
echo 2 > /proc/irq/$(awk -F":" "/usb1/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/usb2/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity 2> /dev/null
echo 4 > /proc/irq/$(awk -F":" "/usb3/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity 2> /dev/null
echo 4 > /proc/irq/$(awk -F":" "/owl_dma0/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 8 > /proc/irq/$(awk -F":" "/ethernet_mac/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 8 > /proc/irq/$(awk -F":" "/sdcard/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
;;
s5p6818) # NanoPi M3: dw-mci on cpu1, USB host on cpu2, GbE on cpu3, USB OTG on cpu4, video-codec on cpu5
for i in $(awk -F':' '/dw-mci/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 1 > /proc/irq/$i/smp_affinity_list
done
echo 2 > /proc/irq/$(awk -F":" "/usb3/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 3 > /proc/irq/$(awk -F":" "/eth0/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
echo 4 > /proc/irq/$(awk -F":" "/usb1/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity_list
for i in $(awk -F':' '/c0080000.video-codec/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 5 > /proc/irq/$i/smp_affinity_list
done
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
;;
sun4i | sun5i | rda8810) # only one core, nothing to improve
:
;;
sun6i) # Banana Pi M2: process eth0 on cpu3, SDIO on cpu2, USB on cpu1
for i in $(awk -F':' '/hcd:usb/{print $1}' /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F':' '/sunxi-mmc/{print $1}' /proc/interrupts | sed 's/\ //g'); do
echo 4 > /proc/irq/$i/smp_affinity
done
echo 8 > /proc/irq/$(awk -F":" '/eth0/ {print $1}' < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
;;
sun7i) # try to redistribute eth0 irq to dedicated core
echo 2 > /proc/irq/$(awk -F":" '/eth0/ {print $1}' < /proc/interrupts | sed 's/\ //g')/smp_affinity 2> /dev/null
;;
sun8i*) # H3/R40/V40 boards, try to do the best based on specific board since interfaces vary a lot
# 10 or 120 sec user feedback that the board is ready after 1st login with 3.4 kernel
SwapState="$(grep swap /etc/fstab)"
if [ "X${SwapState}" != "X" ]; then
(echo heartbeat > /sys/class/leds/*green*/trigger) 2> /dev/null
[ -f "/root/.not_logged_in_yet" ] && BlinkTime=120 || BlinkTime=10
(sleep ${BlinkTime} && (echo default-on > /sys/class/leds/*green*/trigger) 2> /dev/null) &
fi
# check kernel version for IRQ/module names
case ${KERNELID} in
3*)
# BSP kernel
GbE="gmac0"
WiFi="wlan0"
USB1="usb2"
USB2="usb3"
USB3="usb4"
;;
*)
# Mainline kernel
GbE="eth0"
WiFi="wlan0"
USB1="usb3"
USB2="usb4"
USB3="usb5"
;;
esac
# Assign 1st and 2nd USB port to cpu1 and cpu2 on every sun8i board
echo 2 > /proc/irq/$(awk -F":" "/${USB1}/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/${USB2}/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
case ${BOARD_NAME} in
"Orange Pi+" | "Orange Pi+ 2" | "Orange Pi+ 2E" | "Banana Pi M2*" | "NanoPi M1 Plus")
# Send GBit Ethernet IRQs to cpu3
echo 8 > /proc/irq/$(awk -F":" "/${GbE}/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
;;
"NanoPi M1" | "Orange Pi PC Plus" | "Orange Pi PC +" | "Orange Pi PC" | "NanoPi Neo" | "Orange Pi Zero")
# Send 3rd USB port's IRQs to cpu3
echo 8 > /proc/irq/$(awk -F":" "/${USB3}/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
;;
"Orange Pi Lite" | "NanoPi Air" | "Lime A33" | "Orange Pi Zero Plus 2"*)
# Send SDIO/mmc IRQs to cpu3
for i in $(awk -F':' '/sunxi-mmc/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 8 > /proc/irq/$i/smp_affinity
done
;;
"Beelink X2" | "Orange Pi R1" | "ZeroPi")
# Wifi module reload workaround / fix
[[ -n $(lsmod | grep 8189es) && "${BOARD_NAME}" != "ZeroPi" ]] && rmmod 8189es && modprobe 8189es
# Send SDIO to cpu1, USB to cpu2, Ethernet to cpu3
for i in $(awk -F':' '/sunxi-mmc/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 2 > /proc/irq/$i/smp_affinity
done
for i in $(awk -F':' '/hcd:usb/{print $1}' < /proc/interrupts | sed 's/\ //g'); do
echo 4 > /proc/irq/$i/smp_affinity
done
echo 8 > /proc/irq/$(awk -F":" "/${GbE}/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
;;
esac
;;
sun50i* | sunxi64*) # A64/H5 based boards like Pine64, OPi PC 2, NanoPi NEO 2
# Send IRQs for the lower real USB port (usb2) to cpu2 and for the upper (OTG/usb1) to cpu1
echo 2 > /proc/irq/$(awk -F":" "/usb1/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 4 > /proc/irq/$(awk -F":" "/usb2/ {print \$1}" < /proc/interrupts | sed 's/\ //g')/smp_affinity
echo 8 > /proc/irq/$(awk -F":" "/sunxi-mmc/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -n1)/smp_affinity
echo 8 > /proc/irq/$(awk -F":" "/eth/ {print \$1}" < /proc/interrupts | sed 's/\ //g' | head -n1)/smp_affinity
echo 7 > /sys/class/net/eth0/queues/rx-0/rps_cpus
# OrangePi win GMAC is very unstable on gigabit. Limit it down to 100Mb solve problems
[[ $BOARD == orangepiwin && $BRANCH == default ]] && ethtool -s eth0 speed 100 duplex full
;;
esac
} # prepare_board
add_usb_storage_quirks() {
# check for /boot/armbianEnv.txt existence
[ -f /boot/armbianEnv.txt ] || return
# cleanup. add LF. This prevents adding parameters to the same line
echo "" >> /boot/armbianEnv.txt
sed -i '/^$/d;$G' /boot/armbianEnv.txt
sed -i '/^$/d;$G' /boot/armbianEnv.txt
# cleanup. remove empty lines in the middle
sed -i '/^$/d' /boot/armbianEnv.txt
# preserve old contents if existent
TMPFILE=$(mktemp /tmp/${0##*/}.XXXXXX)
trap "sleep 1 ; rm \"${TMPFILE}\" ; exit 0" 0 1 2 3 15
awk -F"=" '/^usbstoragequirks/ {print $2}' < /boot/armbianEnv.txt | tr -d -c '[:graph:]' > ${TMPFILE}
# UAS blacklist Norelsys NS1068X and NS1066X since broken. Can be removed once
# they're blacklisted upstream
[ -s ${TMPFILE} ] || echo "0x2537:0x1066:u,0x2537:0x1068:u" > ${TMPFILE}
# check for connected Seagate or WD HDD enclosures and blacklist them all
lsusb | awk -F" " '{print "0x"$6}' | sed 's/:/:0x/' | sort | uniq | while read; do
case ${REPLY} in
"0x0bc2:"* | "0x1058:"*)
grep -q "${REPLY}" ${TMPFILE} || sed -i "1 s/\$/,${REPLY}:u/" ${TMPFILE}
;;
esac
done
read USBQUIRKS < ${TMPFILE}
sed -i '/^usbstoragequirks/d' /boot/armbianEnv.txt
echo "usbstoragequirks=${USBQUIRKS}" >> /boot/armbianEnv.txt
sync &
if [ -f /sys/module/usb_storage/parameters/quirks ]; then
echo ${USBQUIRKS} > /sys/module/usb_storage/parameters/quirks
fi
} # add_usb_storage_quirks
update_branch_from_installed_kernel() {
BRANCH=$(dpkg -l | grep -E "linux-image" | grep -E "current|legacy|edge" | awk '{print $2}' | cut -d"-" -f3 | head -1)
if grep -q BRANCH /etc/armbian-release; then
[[ -n ${BRANCH} ]] && sed -i "s/BRANCH=.*/BRANCH=$BRANCH/g" /etc/armbian-release
else
[[ -n ${BRANCH} ]] && echo "BRANCH=$BRANCH" >> /etc/armbian-release
fi
}
case $1 in
*start*)
# set optimal disk scheduler settings
set_io_scheduler &
# hardware preparation
prepare_board &
# add usb quirks
add_usb_storage_quirks &
# update branch in main config
update_branch_from_installed_kernel &
;;
esac

View File

@@ -0,0 +1,68 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
STATE_PATH="$1"
[[ -z "$1" ]] && STATE_PATH="/etc/armbian-leds.conf"
REGEX_BLANK_LINE=$'^\s*$'
REGEX_COMMENT_LINE=$'^#.*$'
REGEX_EXTRACT=$'\[(.*)\]'
REGEX_PARSE=$'(.*)=(.*)'
LED=""
if [[ ! -f $STATE_PATH ]]; then
echo "File $STATE_PATH not found, nothing to do"
exit 0
fi
while read LINE; do
# Blank lines and lines starting with "#" are ignored
[[ "$LINE" =~ $REGEX_BLANK_LINE ]] && continue
[[ "$LINE" =~ $REGEX_COMMENT_LINE ]] && continue
# When line matches the [...] style, assign the content as led base path
if [[ "$LINE" =~ $REGEX_EXTRACT ]]; then
LED=${BASH_REMATCH[1]}
continue
fi
if [[ -z "$LED" ]]; then
echo "Invalid state file, no led path stanza found"
exit 1
fi
[[ "$LINE" =~ $REGEX_PARSE ]]
PARAM=${BASH_REMATCH[1]}
VALUE=${BASH_REMATCH[2]}
if [[ -z $PARAM || -z $VALUE ]]; then
echo "Invalid state file, syntax error in configuration file "
exit 1
fi
# Ignore brightness=0 param, this will reset trigger to none
[[ $PARAM == "brightness" && $VALUE -eq 0 ]] && continue
# Verify the led parameter exists and is writable, otherwise skip to next param
if [[ ! -w "$LED/$PARAM" ]]; then
echo "warning: $LED/$PARAM could not be restored"
continue
fi
# Workaround for trigger=none: led does not clear if trigger is already none.
# Set it to default-on, then will be reset immediately to none to turn it off
[[ "$PARAM" == "trigger" && "$VALUE" == "none" ]] && echo "default-on" > "$LED/$PARAM"
echo "$VALUE" > "$LED/$PARAM"
done < $STATE_PATH
exit 0

View File

@@ -0,0 +1,62 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
STATE_PATH="$1"
[[ -z "$1" ]] && STATE_PATH="/etc/armbian-leds.conf"
# Regular expression to extract the trigger from the led trigger file
REGEX=$'\[(.*)\]'
CMD_FIND=$(which find)
# Retrieve the trigger for a specific led and stores the entry in a destination state file
# Also retrieve all the writable parameters for a led and stores them in a destination state file
# $1 = base led path
# $2 = path of destination state file
function store_led() {
PATH="$1"
TRIGGER_PATH="$1/trigger"
DESTINATION="$2"
TRIGGER_CONTENT=$(<$TRIGGER_PATH)
[[ "$TRIGGER_CONTENT" =~ $REGEX ]]
TRIGGER_VALUE=${BASH_REMATCH[1]}
echo "[$LED]" >> $STATE_PATH
echo "trigger=$TRIGGER_VALUE" >> $DESTINATION
# In case the trigger is any of the kbd-*, don't store any other parameter
# This avoids num/scroll/capslock from being restored at startup
[[ "$TRIGGER_VALUE" =~ kbd-* ]] && return
COMMAND_PARAMS="$CMD_FIND $PATH/ -maxdepth 1 -type f ! -iname uevent ! -iname trigger -perm /u+w -printf %f\\n"
PARAMS=$($COMMAND_PARAMS)
for PARAM in $PARAMS; do
PARAM_PATH="$PATH/$PARAM"
VALUE=$(<$PARAM_PATH)
echo "$PARAM=$VALUE" >> $DESTINATION
done
}
# zeroing current state file if existing
[[ -f $STATE_PATH ]] && echo -n > $STATE_PATH
for LED in /sys/class/leds/*; do
[[ -d "$LED" ]] || continue
store_led $LED $STATE_PATH
echo >> $STATE_PATH
done

View File

@@ -0,0 +1,160 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
SIZE=50M
USE_RSYNC=true
ENABLED=false
[ -f /etc/default/armbian-ramlog ] && . /etc/default/armbian-ramlog
[ "$ENABLED" != true ] && exit 0
# Never touch anything below here. Only edit /etc/default/armbian-ramlog
HDD_LOG=/var/log.hdd
RAM_LOG=/var/log
LOG2RAM_LOG="${HDD_LOG}/armbian-ramlog.log"
LOG_OUTPUT="tee -a $LOG2RAM_LOG"
isSafe () {
[ -d $HDD_LOG ] || (echo "ERROR: $HDD_LOG doesn't exist! Can't sync." >&2 ; exit 1)
NoCache=$(command -v nocache 2>/dev/null)
}
RecreateLogs (){
# in case of crash those services don't start if there are no dirs & logs
check_if_installed apache2 && [ ! -d /var/log/apache2 ] && mkdir -p /var/log/apache2
check_if_installed cron-apt && [ ! -d /var/log/cron-apt ] && \
(mkdir -p /var/log/cron-apt ; touch /var/log/cron-apt/log)
check_if_installed proftpd-basic && [ ! -d /var/log/proftpd ] && \
(mkdir -p /var/log/proftpd ; touch /var/log/proftpd/controls.log)
check_if_installed nginx && [ ! -d /var/log/nginx ] && \
(mkdir -p /var/log/nginx ; touch /var/log/nginx/access.log ; touch /var/log/nginx/error.log)
check_if_installed lighttpd && [ ! -d /var/log/lighttpd ] && \
(mkdir -p /var/log/lighttpd ; touch /var/log/lighttpd/access.log ; touch /var/log/lighttpd/error.log)
check_if_installed samba && [ ! -d /var/log/samba ] && mkdir -p /var/log/samba
check_if_installed unattended-upgrades && [ ! -d /var/log/unattended-upgrades ] && mkdir -p /var/log/unattended-upgrades
return 0
}
syncToDisk () {
isSafe
echo -e "\n\n$(date): Syncing logs to storage\n" | $LOG_OUTPUT
if [ "$USE_RSYNC" = true ]; then
${NoCache} rsync -aXWv \
--exclude "lost+found" --exclude armbian-ramlog.log \
--exclude 'journal*' --one-file-system \
--links \
${XTRA_RSYNC_TO[@]+"${XTRA_RSYNC_TO[@]}"} \
$RAM_LOG/ $HDD_LOG/ 2>&1 | $LOG_OUTPUT
else
rm -f $RAM_LOG/journal # linked journal cannot copied onto itself, it will be re-created below
${NoCache} cp -rfup $RAM_LOG -T $HDD_LOG 2>&1 | $LOG_OUTPUT
fi
if [ ! -L $RAM_LOG/journal ] && [ -d $RAM_LOG/journal ]; then # move persistent journal to disk
systemctl stop systemd-journald # journal folder can be in use
if [ -d $HDD_LOG/journal ]; then # optional backup for diagnosis
mv $HDD_LOG/journal $HDD_LOG/journal-$(date +"%Y%M%d-%T")
fi
mv $RAM_LOG/journal $HDD_LOG/journal
systemctl start systemd-journald
fi
if [ ! -L $RAM_LOG/journal ] && [ -d $HDD_LOG/journal ]; then # link persistent journal if applicable
ln -s ${HDD_LOG}/journal ${RAM_LOG}/
fi
if [ -z "`grep ^Storage=volatile /etc/systemd/journald.conf`" ] ;then # flush to disk when applicable
journalctl --flush # this will flush to persistent log
journalctl --relinquish-var # restart volatile logging
fi
sync /
}
syncFromDisk () {
isSafe
echo -e "\n\n$(date): Loading logs from storage\n" | $LOG_OUTPUT
if [ "$USE_RSYNC" = true ]; then
${NoCache} rsync -aXWv --delete \
--exclude "lost+found" --exclude armbian-ramlog.log \
--exclude '*.gz' --exclude '*.xz' --exclude='*.[0-9]' \
--links \
--exclude 'journal*' --one-file-system \
${XTRA_RSYNC_FROM[@]+"${XTRA_RSYNC_FROM[@]}"} \
$HDD_LOG/ $RAM_LOG/ 2>&1 | $LOG_OUTPUT
else
${NoCache} find $HDD_LOG/* -maxdepth 1 -type f -not \( -name '*.[0-9]' -or -name '*.xz*' -or -name '*.gz' -or -name 'journal*' \) | xargs cp -ut $RAM_LOG/
fi
if [ ! -L $RAM_LOG/journal ] && [ -d $HDD_LOG/journal ]; then # link persistent journal if applicable
ln -s ${HDD_LOG}/journal ${RAM_LOG}/
fi
sync /
}
check_if_installed () {
local DPKG_Status="$(dpkg -s "$1" 2>/dev/null | awk -F": " '/^Status/ {print $2}')"
if [[ "X${DPKG_Status}" = "X" || "${DPKG_Status}" = *deinstall* ]]; then
return 1
else
return 0
fi
}
case "$1" in
start)
[ -d $HDD_LOG ] || mkdir -p $HDD_LOG
mount --bind $RAM_LOG $HDD_LOG
mount --make-private $HDD_LOG
# Check whether zram device is available or we need to use tmpfs
LOG_TYPE="tmpfs"
for rd in /dev/zram*; do
if [[ "$(e2label $rd)" == "log2ram" ]]; then
LOG_TYPE="zram"
break
fi
done
case $LOG_TYPE in
zram)
echo -e "Mounting $rd as $RAM_LOG \c" | $LOG_OUTPUT
mount -o discard $rd $RAM_LOG 2>&1 | $LOG_OUTPUT
;;
tmpfs)
echo -e "Setting up $RAM_LOG as tmpfs \c" | $LOG_OUTPUT
mount -t tmpfs -o nosuid,noexec,nodev,mode=0755,size=$SIZE armbian-ramlog $RAM_LOG 2>&1 | $LOG_OUTPUT
;;
esac
syncFromDisk
RecreateLogs
;;
stop)
syncToDisk
umount -l $RAM_LOG
umount -l $HDD_LOG
;;
write)
syncToDisk
;;
postrotate)
cd /var/log.hdd/
find . -type f -print | grep -E -v "(\.gz|\.xz|\.[0-9]|armbian-ramlog)" | while IFS= read -r file
do
dest="/var/log/$file"
cat $file > $dest
done
;;
*)
echo "Usage: ${0##*/} {start|stop|write}" >&2
exit 1
;;
esac

View File

@@ -0,0 +1,305 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
. /etc/armbian-release
. /lib/init/vars.sh
. /lib/lsb/init-functions
. /usr/lib/armbian/armbian-common
do_expand_partition()
{
local partdev=$1
echo -e "\n### [resize2fs] Trying to resize partition $partdev:\n"
# make sure the target is a partition
local parttype=$(lsblk -n -o TYPE $partdev | head -1)
if [[ "$parttype" != "part" ]]; then
echo -e "\n$partdev isn't a partition: $parttype" >&2
return 1
fi
local diskdevname=$(lsblk -n -o PKNAME $partdev | head -1) # i.e. mmcblk0 or sda
# due to the bug in util-linux 2.34 which fails to show device, let's use this failover:
[[ -z $diskdevname ]] && diskdevname=$(echo $partdev | sed -e "s/^\/dev\///" | sed "s/p.*//")
local diskdev="/dev/$diskdevname" # i.e. /dev/mmcblk0, /dev/sda
echo "diskdevname: $diskdevname"
echo "diskdev: $diskdev"
# detect partindex
local partindex="$(echo $partdev | sed "s|^$diskdev||" | sed 's/^p//')" # i.e. 1
if [[ -n "$(echo "$partindex" | tr -d '[:digit:]')" ]]; then
echo -e "\nFail to detect partindex: $partindex" >&2
return 1
fi
echo "partindex: $partindex"
# find the target part's boundaries
local partstart=$(parted $diskdev unit s print -sm | awk -F':' "NR>=3{if(\$1 == $partindex){print \$2}}" | sed 's/s//')
local partend=$(parted $diskdev unit s print -sm | awk -F':' "NR>=3{if(\$1 == $partindex){print \$3}}" | sed 's/s//')
if [[ -z "$partstart" ]] || [[ -z "$partend" ]]; then
echo -e "\nFail to find the target partition" >&2
return 1
fi
echo "partstart: ${partstart}s"
echo "partend: ${partend}s"
# check if it's the last partition in logical layout
# Note: the order may be different between partition table and logical layout
local list=$(parted $diskdev unit s print -sm | awk -F':' "NR>=3{if(\$2 - $partstart > 0){print \$1}}")
if [[ -n "$list" ]]; then
echo -e "\nThe target partition isn't the last partition in logical layout" >&2
echo "Partition ${list[*]} behind it" >&2
return 1
fi
local capacity=$(parted $diskdev unit s print -sm | awk -F':' 'NR==2{print $2}' | sed 's/s//')
local sectorsize=$(parted $diskdev unit s print -sm | awk -F':' 'NR==2{print $4}')
echo "capacity: ${capacity}s"
echo "sectorsize: ${sectorsize}B"
# check whether a resizing rule is defined. We will take this value if it's not too low. In
# this case the value will be ignored and resizing to the whole card size happens.
if [[ -f /root/.rootfs_resize ]]; then
read RESIZE_VALUE </root/.rootfs_resize
echo "Resize rule $RESIZE_VALUE defined for root partition"
case $RESIZE_VALUE in
*%)
# percentage value
local percentage=$(echo $RESIZE_VALUE | tr -c -d '[:digit:]')
local lastsector=$(( $capacity * $percentage / 100 ))
;;
*s)
# sector value, we use it directly
local lastsector=$(echo $RESIZE_VALUE | tr -c -d '[:digit:]')
;;
*B)
# byte value
local byte=$(echo $RESIZE_VALUE | tr -c -d '[:digit:]')
local lastsector=$(( $byte / $sectorsize ))
;;
*)
echo -e "\nUnknown rule: $RESIZE_VALUE" >&2
return 1;
;;
esac
# if remain more than 1GiB then create another partition
if [[ $(( $sectorsize * ($capacity - $lastsector) )) -ge $(( 1 * 1024 * 1024 * 1024 )) ]]; then
local newpartition=$(( $capacity * 99 / 100 ))
fi
else
# check device capacity. If 4GiB or below do not use whole card but leave a 5% spare area
# to help older cards with wear leveling and garbage collection. In case this reduced card
# capacity is less than the actual image capacity this is a clear sign that someone wants
# to use Armbian on a card of inappropriate size so he gets what he deserves (at least he
# should know what he's doing)
if [[ $(( $sectorsize * $capacity )) -lt $(( 4 * 1024 * 1024 * 1024 )) ]]; then # 4 GiB or less
# Leave 5 percent unpartitioned
local lastsector=$(( $capacity * 95 / 100 ))
echo "4GiB or smaller media - leaving 5% spare area"
elif [[ $(( $sectorsize * $capacity )) -lt $(( 8 * 1024 * 1024 * 1024 )) ]]; then # 8 GiB or less
# Leave 2 percent unpartitioned
local lastsector=$(( $capacity * 98 / 100 ))
echo "8GiB or smaller media - leaving 2% spare area"
else
# Leave 1 percent unpartitioned
local lastsector=$(( $capacity * 99 / 100 ))
echo "Leaving 1% spare area"
fi
fi
# use 16MiB to align partitions since this is the erase block size of more recent SD cards
local lastsector=$(( $lastsector - ($lastsector % (16 * 1024 * 1024 / $sectorsize)) ))
[[ -n "$newpartition" ]] && local newpartition=$(( $newpartition - ($newpartition % (16 * 1024 * 1024 / $sectorsize)) ))
if [[ $lastsector -lt $partend ]]; then
echo -e "\n${partend} is larger than ${lastsector}s, that means you trying to shrink filesystem. Sorry, this tool designed for expanding only." >&2
return 1
elif [[ $lastsector -eq $partend ]]; then
echo -e "\nSame size. Skip" >&2
return 0
fi
if [[ $newpartition -le $(( $lastsector + 1 )) ]]; then
unset newpartition
fi
echo -e "Old partition table:\n"
cat /proc/partitions
# Start resizing
echo -e "\nExecuting fdisk:"
local partnum=$(parted $diskdev unit s print -sm | awk 'END{print NR-2}')
local fdisk_version=$(fdisk --version | awk '{print $NF}' | grep -oE "^[[:digit:]]\.[[:digit:]]+")
if [[ $partnum == 1 ]] && awk "BEGIN{exit ! ($fdisk_version >= 2.27 )}"; then
# if dealing with fdisk from util-linux 2.27+ we need a workaround for just 1 partition
# though it does not break anything - just prevents an "unexpected command" to fdisk
# https://github.com/igorpecovnik/lib/issues/353#issuecomment-224728506
{
echo d
echo n; echo p; echo $partindex; echo $partstart; echo $lastsector
echo w
} | fdisk $diskdev
else
{
echo d; echo $partindex
echo n; echo p; echo $partindex; echo $partstart; echo $lastsector
echo w
} | fdisk $diskdev
fi
if [[ -n $newpartition ]]; then
{
echo n; echo p; echo ; echo $(( $lastsector + 1 )); echo $newpartition
echo w
} | fdisk $diskdev
fi
echo -e "\nExecuting partprobe:"
# Workaround for Kernel bug in 5.8.y and up. Ignore partprobe returning error and inticating that fs is not expended while it is
KERNELID=$(uname -r | awk -F'.' '{print ($1 * 100) + $2}')
if ! partprobe $rootdev && [[ ${KERNELID} -le 507 ]]; then
echo -e "\n### [resize2fs] Automated reboot needed to finish the resize procedure"
touch /var/run/resize2fs-reboot
fi
local partsize=$(lsblk -n -b -o SIZE $partdev | head -1)
local actualsize=$(( $sectorsize * ($lastsector - $partstart + 1) ))
if [[ $actualsize -ne $partsize ]]; then
echo -e "\n### [resize2fs] Automated reboot needed to finish the resize procedure"
touch /var/run/resize2fs-reboot
fi
echo -e "New partition table:\n"
cat /proc/partitions
return 0
}
do_resize_crypt()
{
local dev=$1
local parentdev=$2
local name=$(lsblk -n -o NAME $dev | head -1) # i.e. armbian-root
echo -e "\n### [resize2fs] Start resizing LUKS container now\n"
# It's probably no need to run 'cryptsetup resize'.
# After reboot, it will auto resize to adapte the partition
# 'cryptsetup resize' requires passphrase, so it will fail.
cryptsetup resize $name
local parentsize=$(lsblk -n -b -o SIZE $parentdev | head -1)
local sectorsize=$(cryptsetup status $name | awk -F':' '/^ *sector size/ {print $2}' | tr -c -d '[:digit:]')
local offset=$(cryptsetup status $name | awk -F':' '/^ *offset/ {print $2}' | tr -c -d '[:digit:]')
local size=$(cryptsetup status $name | awk -F':' '/^ *size/ {print $2}' | tr -c -d '[:digit:]')
local actualsize=$(( $sectorsize * ($offset + $size) ))
if [[ $actualsize -ne $parentsize ]]; then
echo -e "\n### [resize2fs] Automated reboot needed to finish the resize procedure"
touch /var/run/resize2fs-reboot
fi
}
do_expand_filesystem()
{
local partdev=$1
local mountpoint=$2
local fstype=$(findmnt -n -o FSTYPE $mountpoint) # i.e. ext4 or btrfs
echo -e "\n### [resize2fs] Trying to resize $fstype filesystem on $partdev:\n"
case $fstype in
ext4)
echo "Running 'resize2fs $partdev' now..."
resize2fs $partdev
;;
btrfs)
echo "Running 'btrfs filesystem resize max $mountpoint' now..."
btrfs filesystem resize max $mountpoint
;;
nilfs2)
echo "Running 'nilfs2 filesystem resize max $mountpoint' now..."
nilfs-resize -v -y $partdev
;;
*)
echo "Unsupported filesystem: $fstype"
echo "Trying to run 'resize2fs $partdev' now..."
resize2fs $partdev
return
;;
esac
# check whether reboot is necessary for resize2fs to take effect
local devsize=$(lsblk -n -b -o SIZE $partdev | head -1)
local fssize=$(findmnt -n -b -o SIZE --target $mountpoint)
if [[ $(( 100 * $fssize / $devsize )) -lt 90 ]]; then
echo -e "\n### [resize2fs] Automated reboot needed to finish the resize procedure"
touch /var/run/resize2fs-reboot
fi
}
main()
{
rm /var/run/resize2fs-reboot 2>/dev/null
# skip resizing if explicitly disabled
if [[ -f /root/.no_rootfs_resize ]]; then
systemctl disable armbian-resize-filesystem
exit 0
fi
# Logging header
CPU_ARCH=$(lscpu | awk '/Architecture/ {print $2}')
DISTRO_ARCH=$(dpkg --print-architecture)
KERNELID=$(uname -r)
echo "$(date) | ${BOARD_NAME} | ${VERSION} | ${DISTRO_ARCH} | ${CPU_ARCH} | ${KERNELID}"
# trim any btrfs subvolume identifier given in square brackets (e.g. /dev/mapper/armbian-root[/@])
local rootdev=$(findmnt -n -o SOURCE / | sed 's~\[.*\]~~') # i.e. /dev/mmcblk0p1, /dev/sda1 or /dev/mapper/armbian-root
# check for crypt
local cryptname=""
if [[ "$(lsblk -n -o TYPE $rootdev | head -1)" == "crypt" ]]; then
local cryptname=$(lsblk -n -o NAME $rootdev | head -1) # i.e. armbian-root
local parent_uuid=$(cat /etc/crypttab | awk "{if(\$1 == \"$cryptname\"){print \$2}}" | sed 's/UUID=//')
local parentdev=$(blkid -U $parent_uuid) # i.e. /dev/mmcblk0p1 or /dev/sda1
do_expand_partition "$parentdev"
# resize LUKS container
do_resize_crypt "$rootdev" "$parentdev"
else
# check if growroot (from cloud-initramfs-growroot package) is installed.
# despite it's name, that package does NOT require cloud-init.
# it will resize the *partition* which root filesystem on during initramfs.
# in this case do nothing here, just run resize2fs (growroot does not handle that).
# Note: it can't handle crypt device
if [[ -f /usr/share/initramfs-tools/hooks/growroot ]] || [[ -f /usr/share/initramfs-tools/scripts/local-bottom/growroot ]]; then
echo "partition resize skipped: growroot detected."
else
do_expand_partition "$rootdev"
fi
fi
do_expand_filesystem "$rootdev" "/"
# disable itself
[[ ! -f /var/run/resize2fs-reboot ]] && systemctl disable armbian-resize-filesystem
exit 0
}
case "$1" in
start)
touch ${Log}
chmod 644 ${Log}
main |& tee -a ${Log}
;;
*)
echo "Usage: $0 start"
exit 0
;;
esac

View File

@@ -0,0 +1,41 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
#
# truncate, save and clean logs if they get over 75% of the /var/log size
# working only when armbian-ramlog is enabled
treshold=75 # %
JOURNAL_SIZE=5M # size to shrink systemd-journal
[ -f /etc/default/armbian-ramlog ] && . /etc/default/armbian-ramlog
[ "$ENABLED" != true ] && exit 0
if [ -z "`grep ^Storage=volatile /etc/systemd/journald.conf`" -a -z "$(ls -A /run/log/journal)" ] ;then
journalctl --relinquish-var # make sure to do volatile logging until the next flush
fi
logusage=$(df /var/log/ --output=pcent | tail -1 |cut -d "%" -f 1)
if [ $logusage -ge $treshold ]; then
# remove journal backup files created by armbian-ramdisk in case of duplicate journals directories
rm -rf /var/log.hdd/journal-*
# write to SD
/usr/lib/armbian/armbian-ramlog write >/dev/null 2>&1
# rotate logs on "disk"
/usr/sbin/logrotate --force /etc/logrotate.conf
# truncate
/usr/bin/find /var/log -name '*.log' -or -name '*.xz' -or -name 'lastlog' -or -name 'messages' -or -name 'debug' -or -name 'syslog' | xargs -r truncate --size 0
/usr/bin/find /var/log -name 'btmp' -or -name 'wtmp' -or -name 'faillog' -or -name 'firewalld' | xargs -r truncate --size 0
/usr/bin/find /var/log -name 'mail.err' -or -name 'mail.info' -or -name 'mail.warning' | xargs -r truncate --size 0
# remove
/usr/bin/find /var/log -name '*.[0-9]' -or -name '*.gz' | xargs -r rm -f
# vacuum systemd-journald
[ -d /var/log/journal ] && journalctl --quiet --vacuum-size=${JOURNAL_SIZE}
# remove old archived journal files modified more than 1 day ago
[ -d /var/log.hdd/journal ] && find /var/log.hdd/journal -ctime 1 \( -name '*@*' -o -name '*~' \) -delete
fi

View File

@@ -0,0 +1,157 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
# Functions:
#
# activate_zram
# activate_zram_swap
# activate_ramlog_partition
# activate_compressed_tmp
# Read in basic OS image information
. /etc/armbian-release
# and script configuration
. /usr/lib/armbian/armbian-common
# It's possible to override SWAP, ZRAM_PERCENTAGE, MEM_LIMIT_PERCENTAGE, ZRAM_MAX_DEVICES,
# SWAP_ALGORITHM, RAMLOG_ALGORITHM, TMP_ALGORITHM and TMP_SIZE here:
ENABLED=false
[ -f /etc/default/armbian-zram-config ] && . /etc/default/armbian-zram-config
# Exit if not Enabled
[[ "$ENABLED" != "true" ]] && exit 0
# Do not interfere with already present zram-config package
dpkg -l | grep -q 'zram-config' && exit 0
activate_zram() {
# Load zram module with n instances for swap: one per CPU core, $ZRAM_MAX_DEVICES
# defines the maximum, on modern kernels we overwrite this with 1 and rely on
# max_comp_streams being set to count of CPU cores or $ZRAM_MAX_DEVICES
uname -r | grep -q '^3.' && zram_max_devs=${ZRAM_MAX_DEVICES:=4} || zram_max_devs=1
cpu_cores=$(grep -c '^processor' /proc/cpuinfo | sed 's/^0$/1/')
[[ ${cpu_cores} -gt ${zram_max_devs} ]] && zram_devices=${zram_max_devs} || zram_devices=${cpu_cores}
module_args="$(modinfo zram | awk -F" " '/num_devices/ {print $2}' | cut -f1 -d:)"
[[ -n ${module_args} ]] && modprobe zram ${module_args}=$(( zram_devices + 2 )) || return
swap_algo=${SWAP_ALGORITHM:=lzo}
# Expose 50% of real memory as swap space by default
zram_percent=${ZRAM_PERCENTAGE:=50}
mem_info=$(LC_ALL=C free -w 2>/dev/null | grep "^Mem" || LC_ALL=C free | grep "^Mem")
mem_info=$(echo $mem_info | awk '{print $2}')
memory_total=$(( mem_info * 1024 ))
mem_per_zram_device=$(( memory_total * zram_percent / zram_devices / 100 ))
# Limit memory available to zram to 50% by default
mem_limit_percent=${MEM_LIMIT_PERCENTAGE:=50}
mem_limit_per_zram_device=$(( memory_total * mem_limit_percent / zram_devices / 100 ))
}
activate_zram_swap() {
# Return is SWAP is disabled (enabled by default)
[[ -n "$SWAP" && "$SWAP" != "true" ]] && return;
# Disable zswap if zram should be used. To make use of zswap instead a
# swap file or partition on *capable* storage needs to be chosen and
# defined as swap and also in /etc/default/armbian-zram-config SWAP=false
# needs to be set.
echo 0 >/sys/module/zswap/parameters/enabled 2>/dev/null
# Limit Journal size to 20Mb
sed -i "s/.*SystemMaxUse=$/SystemMaxUse=20M/" /etc/systemd/journald.conf
for (( i=1; i<=zram_devices; i++ )); do
swap_device=$(zramctl -f |sed 's/\/dev\///')
[[ ! ${swap_device} =~ ^zram ]] && printf "\n### No more available zram devices (%s)\n" "${swap_device}" >> ${Log} && exit 1;
if [ -f /sys/block/${swap_device}/comp_algorithm ]; then
# set compression algorithm, if defined as lzo choose lzo-rle if available
# https://www.phoronix.com/scan.php?page=news_item&px=ZRAM-Linux-5.1-Better-Perform
grep -q 'lzo-rle' /sys/block/${swap_device}/comp_algorithm && \
[[ "X${swap_algo}" = "Xlzo" ]] && swap_algo="lzo-rle"
echo ${swap_algo} >/sys/block/${swap_device}/comp_algorithm 2>/dev/null
fi
if [ "X${ZRAM_BACKING_DEV}" != "X" ]; then
echo ${ZRAM_BACKING_DEV} >/sys/block/${swap_device}/backing_dev
fi
echo -n ${ZRAM_MAX_DEVICES:=4} > /sys/block/${swap_device}/max_comp_streams
echo -n ${mem_per_zram_device} > /sys/block/${swap_device}/disksize
echo -n ${mem_limit_per_zram_device} > /sys/block/${swap_device}/mem_limit
mkswap /dev/${swap_device}
swapon -p 5 /dev/${swap_device}
done
# Swapping to HDDs is stupid so switch to settings made for flash memory and zram/zswap
echo 0 > /proc/sys/vm/page-cluster
printf "\n### Activated %s %s zram swap devices with %dMB each.\n" "${zram_devices}" "${swap_algo}" "$((mem_per_zram_device / 1048576))" >> ${Log}
} # activate_zram_swap
activate_ramlog_partition() {
# /dev/zram0 will be used as a compressed /var/log partition in RAM if
# ENABLED=true in /etc/default/armbian-ramlog is set
ENABLED=$(awk -F"=" '/^ENABLED/ {print $2}' /etc/default/armbian-ramlog)
[[ "$ENABLED" != "true" ]] && return
log_device=$(zramctl -f |sed 's/\/dev\///')
[[ ! ${log_device} =~ ^zram ]] && printf "\n### No more available zram devices (%s)\n" "${log_device}" >> ${Log} && exit 1;
# read size also from /etc/default/armbian-ramlog
ramlogsize=$(awk -F"=" '/^SIZE/ {print $2}' /etc/default/armbian-ramlog)
disksize=$(sed -e 's/M$/*1048576/' -e 's/K$/*1024/' <<<${ramlogsize:=50M} | bc)
# choose RAMLOG_ALGORITHM if defined in /etc/default/armbian-zram-config
# otherwise try to choose most efficient compression scheme available.
# See https://patchwork.kernel.org/patch/9918897/
if [ "X${RAMLOG_ALGORITHM}" = "X" ]; then
for algo in lz4 lz4hc quicklz zlib brotli zstd ; do
echo ${algo} >/sys/block/${log_device}/comp_algorithm 2>/dev/null
done
else
echo ${RAMLOG_ALGORITHM} >/sys/block/${log_device}/comp_algorithm 2>/dev/null
fi
echo -n ${disksize} > /sys/block/${log_device}/disksize
# if it fails, select $swap_algo. Workaround for some older kernels
if [[ $? == 1 ]]; then
echo ${swap_algo} > /sys/block/${log_device}/comp_algorithm 2>/dev/null
echo -n ${disksize} > /sys/block/${log_device}/disksize
fi
mkfs.ext4 -O ^has_journal -s 1024 -L log2ram /dev/${log_device}
algo=$(sed 's/.*\[\([^]]*\)\].*/\1/g' </sys/block/${log_device}/comp_algorithm)
printf "### Activated Armbian ramlog partition with %s compression\n" "${algo}" >> ${Log}
} # activate_ramlog_partition
activate_compressed_tmp() {
# create /tmp not as tmpfs but zram compressed if no fstab entry exists
grep -q '^tmpfs /tmp' /etc/mtab && return
tmp_device=$(zramctl -f |sed 's/\/dev\///')
[[ ! ${tmp_device} =~ ^zram ]] && printf "\n### No more available zram devices (%s)\n" "${tmp_device}" >> ${Log} && exit 1;
if [[ -f /sys/block/${tmp_device}/comp_algorithm ]]; then
if [ "X${TMP_ALGORITHM}" = "X" ]; then
echo ${swap_algo} >/sys/block/${tmp_device}/comp_algorithm 2>/dev/null
else
echo ${TMP_ALGORITHM} >/sys/block/${tmp_device}/comp_algorithm 2>/dev/null
fi
fi
[[ -z ${TMP_SIZE} ]] && echo -n $(( memory_total / 2 )) > /sys/block/${tmp_device}/disksize || echo -n ${TMP_SIZE} > /sys/block/${tmp_device}/disksize
mkfs.ext4 -O ^has_journal -s 1024 -L tmp /dev/${tmp_device}
mount -o nosuid,discard /dev/${tmp_device} /tmp
chmod 1777 /tmp
algo=$(sed 's/.*\[\([^]]*\)\].*/\1/g' </sys/block/${tmp_device}/comp_algorithm)
printf "\n### Activated %s compressed /tmp\n" "${algo}" >> ${Log}
} # activate_compressed_tmp
case $1 in
*start*)
activate_zram
activate_zram_swap
activate_ramlog_partition
activate_compressed_tmp
;;
esac

View File

@@ -0,0 +1 @@
../../share/chromium/master_preferences

View File

@@ -0,0 +1 @@
armbian-install

View File

@@ -0,0 +1,99 @@
#!/bin/bash
# Copyright (c) 2017 The Armbian Project https://www.armbian.com/
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
if [[ ! -n $1 ]]; then
echo >&2 "Usage: $0 <overlay_source_file.dts>"
exit -1
fi
if [[ $EUID -ne 0 ]]; then
echo >&2 "This program must be run with superuser rights"
exit -1
fi
if [[ ! -f $1 ]]; then
echo >&2 "Can't open file $1. File does not exist?"
exit -1
fi
if [[ $1 == *.dts ]]; then
fname=$(basename $1 .dts)
else
echo >&2 "Overlay source file name should have the .dts extension"
exit -1
fi
if [[ ! -f /etc/armbian-release || ! -f /boot/armbianEnv.txt ]]; then
echo >&2 "Armbian is not installed properly. Missing armbian-release or armbianEnv.txt"
exit -1
fi
. /etc/armbian-release
if ! grep -q '^setenv overlay_error' /boot/boot.cmd; then
echo >&2 "Overlays are not supported on ${LINUXFAMILY^} based boards."
exit -1
fi
if [[ -d /lib/modules/$(uname -r)/build/scripts/dtc ]]; then
if [[ ! -x /lib/modules/$(uname -r)/build/scripts/dtc/dtc ]]; then
# Can't use distribution provided (i.e. Bionic) dtc yet
# https://git.kernel.org/pub/scm/utils/dtc/dtc.git/commit/livetree.c?id=bba26a5291c8343101e0296b0e478deb4c9b60b0
echo >&2 "Error: kernel headers are not installed properly"
echo >&2 "Can't find dtc that supports compiling overlays"
echo >&2 "Please install the headers package for kernel $(uname -r)"
exit -1
else
export PATH=/lib/modules/$(uname -r)/build/scripts/dtc/:$PATH
fi
fi
if ! type dtc > /dev/null ; then
echo "Error: dtc not found in PATH"
echo "Please try to install matching kernel headers"
exit -1
fi
if ! grep -q 'symbols' <(dtc --help) ; then
echo "Error: dtc does not support compiling overlays"
# echo "Please try to install matching kernel headers"
exit -1
fi
if [[ ! -d /boot/overlay-user ]]; then
mkdir -p /boot/overlay-user
fi
temp_dir=$(mktemp -d)
echo "Compiling the overlay"
dtc -@ -q -I dts -O dtb -o ${temp_dir}/${fname}.dtbo $1
if [[ $? -ne 0 ]]; then
echo >&2 "Error compiling the overlay"
exit -1
fi
echo "Copying the compiled overlay file to /boot/overlay-user/"
cp ${temp_dir}/${fname}.dtbo /boot/overlay-user/${fname}.dtbo
if grep -q '^user_overlays=' /boot/armbianEnv.txt; then
line=$(grep '^user_overlays=' /boot/armbianEnv.txt | cut -d'=' -f2)
if grep -qE "(^|[[:space:]])${fname}([[:space:]]|$)" <<< $line; then
echo "Overlay ${fname} was already added to /boot/armbianEnv.txt, skipping"
elif grep -q '^user_overlays=\s*$' /boot/armbianEnv.txt; then
sed -i -e "s/^user_overlays=\s*$/user_overlays=${fname}/" /boot/armbianEnv.txt
else
sed -i -e "/^user_overlays=/ s/$/ ${fname}/" /boot/armbianEnv.txt
fi
else
sed -i -e "\$auser_overlays=${fname}" /boot/armbianEnv.txt
fi
echo "Reboot is required to apply the changes"

View File

@@ -0,0 +1,929 @@
#!/bin/bash
#
# Copyright (c) Authors: https://www.armbian.com/authors
#
# Tool to transfer the rootfs of an already running Armbian installation from boot media
# to NAND, eMMC, SATA, NVME or USB storage. In case of eMMC it's also possible to transfer
# the bootloader to eMMC in a single step so from then on running without SD card is
# possible. In case of UEFI it's possible to install it side by side with Windows 10/11 or
# to an empty target.
#
# Import:
# DIR: path to u-boot directory
# write_uboot_platform: function to write u-boot to a block device
# write_uboot_platform_mtd:
# function to write u-boot to a mtd (eg. SPI flash) device
# $1 = u-boot files directory
# $2 = first MTD device path (e.g.: /dev/mtdblock0) - this is for backward compatibility before Armbian 23.nn
# $3 = Log file name
# $4 = :space: separated list of all MTD device names
# Note: MTD char device names are passed in format device_name:partition_label - e.g.: mtd0:SPL
[[ -f /usr/lib/u-boot/platform_install.sh ]] && source /usr/lib/u-boot/platform_install.sh
# ORIGINAL_SCRIPT_NAME: Must be either armbian-install or nand-sata-install
ORIGINAL_SCRIPT_NAME=$(basename $0)
# script configuration - derive from ORIGINAL_SCRIPT_NAME
CWD="/usr/lib/${ORIGINAL_SCRIPT_NAME}"
EX_LIST="${CWD}/exclude.txt"
[ ! -f ${EX_LIST} ] && echo -e "### Board installation issue: File ${EX_LIST} does not exist or is not accessible!\n" && exit 1
[ -f /etc/default/openmediavault ] && echo '/srv/*' >> "${EX_LIST}"
logfile="/var/log/${ORIGINAL_SCRIPT_NAME}.log"
# read in board info
[[ -f /etc/armbian-release ]] && source /etc/armbian-release
backtitle="Armbian for $BOARD_NAME install script, https://www.armbian.com"
title="Armbian installer v${VERSION}"
# exceptions
if grep -q 'sun4i' /proc/cpuinfo; then DEVICE_TYPE="a10";
elif grep -q 'sun5i' /proc/cpuinfo; then DEVICE_TYPE="a13";
else DEVICE_TYPE="a20"; fi
BOOTLOADER="${CWD}/${DEVICE_TYPE}/bootloader"
[ ! -d ${BOOTLOADER} ] && echo -e "### Board installation issue: Directory ${BOOTLOADER} does not exist or is not accessible!\n" && exit 1
FIRSTSECTOR=32768
#recognize_root
root_uuid=$(sed -e 's/^.*root=//' -e 's/ .*$//' < /proc/cmdline)
root_partition=$(blkid | tr -d '":' | grep "${root_uuid}" | awk '{print $1}')
root_partition_name=$(echo $root_partition | sed 's/\/dev\///g')
root_partition_device_name=$(lsblk -ndo pkname $root_partition)
root_partition_device=/dev/$root_partition_device_name
# find targets: legacy SUNXI NAND, EMMC, SATA, NVMe, MTD block and/or MTD char driven flash
[[ -b /dev/nand ]] && nandcheck=$(ls -d -1 /dev/nand* | grep -w 'nand' | awk '{print $NF}');
emmccheck=$(ls -d -1 /dev/mmcblk* 2>/dev/null | grep -w 'mmcblk[0-9]' | grep -v "$root_partition_device");
diskcheck=$(lsblk -l | awk -F" " '/ disk / {print $1}' | grep -E '^sd|^nvme|^mmc' | grep -v "$root_partition_device_name" | grep -v boot)
# Start mtdcheck with probable MTD block device partitions:
mtdcheck=$(grep 'mtdblock' /proc/partitions | awk '{print $NF}' | xargs)
# Append mtdcheck with probable MTD char devices filtered for partition name(s)
# containing "spl" or "boot" case insensitive,
# since we are currently interested in MTD partitions for boot flashing only.
# Note: The following statement will add matching MTD char device names
# combined with partition name (separated from devicename by a :colon:):
# mtd0:partition0_name mtd1:partition1_name ... mtdN:partitionN_name
[[ -f /proc/mtd ]] && mtdcheck="$mtdcheck${mtdcheck:+ }$(grep -i -E '^mtd[0-9]+:.*(spl|boot).*' /proc/mtd | awk '{print $1$NF}' | sed 's/\"//g' | xargs)"
# SD card boot part - to be considered more than one entry on various platforms
# UUID=xxx...
# 1 - Lookup mmc devices excluding the mmc device probably providing the current root partition as well as a probable emmc device found above:
[[ -z $emmccheck ]] && sdblkid=$(blkid -o full /dev/mmcblk*p1 | grep -v "$root_partition_device")
[[ -n $emmccheck ]] && sdblkid=$(blkid -o full /dev/mmcblk*p1 | grep -v "$root_partition_device" | grep -v "$emmccheck")
# 2 - If there is nothing, then lookup any mmc partition matching /dev/mmcblk*p1 excluding probable emmc device found above
[[ -z $sdblkid && -z $emmccheck ]] && sdblkid=$(blkid -o full /dev/mmcblk*p1)
[[ -z $sdblkid && -n $emmccheck ]] && sdblkid=$(blkid -o full /dev/mmcblk*p1 | grep -v "$emmccheck")
# 3 - Extract the UUID=<uuid> from $sdblkid via regex without " - as e.g.: UUID=2e1d1509-a8fc-4f8b-8a51-88fb8593f8d6
sduuid=$(echo "$sdblkid" | sed -nE 's/^.*[[:space:]](UUID="[0-9a-zA-Z-]*").*/\1/p' | tr -d '"')
#recognize EFI
[[ -d /sys/firmware/efi ]] && DEVICE_TYPE="uefi"
efi_partition=$(LC_ALL=C fdisk -l "/dev/$diskcheck" 2>/dev/null | grep "EFI" | awk '{print $1}')
# define makefs and mount options
declare -A mkopts mountopts
# for ARMv7 remove 64bit feature from default mke2fs format features
if [[ $LINUXFAMILY == mvebu ]]; then
mkopts[ext4]='-O ^64bit -qF'
else
mkopts[ext4]='-qF'
fi
mkopts[btrfs]='-f'
mkopts[f2fs]='-f'
mountopts[ext4]='defaults,noatime,commit=600,errors=remount-ro,x-gvfs-hide 0 1'
mountopts[btrfs]='defaults,noatime,commit=600,compress=lzo,x-gvfs-hide 0 2'
mountopts[f2fs]='defaults,noatime,x-gvfs-hide 0 2'
# Create boot and root file system #
#
# "$1" = boot
# "$2" = root (Example: create_armbian "/dev/nand1" "/dev/sda3")
# "$3" = selected UEFI root target
#
create_armbian()
{
[[ -n "$3" ]] && diskcheck=$3
# create mount points, mount and clean
TempDir=$(mktemp -d /mnt/${0##*/}.XXXXXX || exit 2)
sync && mkdir -p "${TempDir}"/bootfs "${TempDir}"/rootfs
if [[ $eMMCFilesystemChoosen =~ ^(btrfs|f2fs)$ ]]; then
[[ -n $1 ]] && mount ${1::-1}"1" "${TempDir}"/bootfs
[[ -n $2 ]] && ( mount -o compress-force=zlib "$2" "${TempDir}"/rootfs 2> /dev/null || mount "$2" "${TempDir}"/rootfs )
else
[[ -n $2 ]] && ( mount -o compress-force=zlib "$2" "${TempDir}"/rootfs 2> /dev/null || mount "$2" "${TempDir}"/rootfs )
[[ -n $1 && $1 != "mtd" ]] && mount "$1" "${TempDir}"/bootfs
fi
rm -rf "${TempDir}"/bootfs/* "${TempDir}"/rootfs/*
# sata root part
# UUID=xxx...
satauuid=$(blkid -o export "$2" | grep -w UUID)
# write information to log
echo -e "\nOld UUID: ${root_uuid}" >> $logfile
echo "SD UUID: $sduuid" >> $logfile
echo "SATA UUID: $satauuid" >> $logfile
echo "eMMC UUID: $emmcuuid $eMMCFilesystemChoosen" >> $logfile
echo "Boot: \$1 $1 $eMMCFilesystemChoosen" >> $logfile
echo "Root: \$2 $2 $FilesystemChoosen" >> $logfile
# calculate usage and see if it fits on destination
USAGE=$(df -BM | grep ^/dev | head -1 | awk '{print $3}' | tr -cd '[0-9]. \n')
DEST=$(df -BM | grep ^/dev | grep "${TempDir}"/rootfs | awk '{print $4}' | tr -cd '[0-9]. \n')
if [[ $USAGE -gt $DEST ]]; then
dialog --title "$title" --backtitle "$backtitle" --colors --infobox\
"\n\Z1Partition too small.\Zn Needed: $USAGE MB Avaliable: $DEST MB" 5 60
umount_device "$1"; umount_device "$2"
exit 3
fi
if [[ $1 == *nand* ]]; then
# creating nand boot. Copy precompiled uboot
rsync -aqc $BOOTLOADER/* "${TempDir}"/bootfs
fi
# write information to log
echo "Usage: $USAGE" >> $logfile
echo -e "Dest: $DEST\n\n/etc/fstab:" >> $logfile
cat /etc/fstab >> $logfile
echo -e "\n/etc/mtab:" >> $logfile
grep '^/dev/' /etc/mtab | grep -E -v "log2ram|folder2ram" | sort >> $logfile
# stop running services
echo -e "\nFiles currently open for writing:" >> $logfile
lsof / 2>/dev/null | awk 'NR==1 || $4~/[0-9][uw]/' | grep -v "^COMMAND" >> $logfile
echo -e "\nTrying to stop running services to minimize open files:\c" >> $logfile
stop_running_services "nfs-|smbd|nmbd|winbind|ftpd|netatalk|monit|cron|webmin|rrdcached" >> $logfile
stop_running_services "fail2ban|ramlog|folder2ram|postgres|mariadb|mysql|postfix|mail|nginx|apache|snmpd" >> $logfile
pkill dhclient 2>/dev/null
LANG=C echo -e "\n\nChecking again for open files:" >> $logfile
lsof / 2>/dev/null | awk 'NR==1 || $4~/[0-9][uw]/' | grep -v "^COMMAND" >> $logfile
# count files is needed for progress bar
dialog --title " $title " --backtitle "$backtitle" --infobox "\n Counting files ... few seconds." 5 60
TODO=$(rsync -ahvrltDn --delete --stats --exclude-from=$EX_LIST / "${TempDir}"/rootfs | grep "Number of files:"|awk '{print $4}' | tr -d '.,')
echo -e "\nCopying ${TODO} files to $2. \c" >> $logfile
# creating rootfs
# Speed copy increased x10
# Variables for interfacing with rsync progress
nsi_conn_path="${TempDir}/nand-sata-install"
nsi_conn_done="${nsi_conn_path}/done"
nsi_conn_progress="${nsi_conn_path}/progress"
mkdir -p "${nsi_conn_path}"
echo 0 >"${nsi_conn_progress}"
echo no >"${nsi_conn_done}"
# Launch rsync in background
{ \
rsync -avrltD --delete --exclude-from=$EX_LIST / "${TempDir}"/rootfs | \
nl | awk '{ printf "%.0f\n", 100*$1/"'"$TODO"'" }' \
> "${nsi_conn_progress}" ;
# create empty persistent journal directory if it exists before install
[ -d /var/log.hdd/journal ] && mkdir "${TempDir}"/rootfs/var/log/journal
# save exit code from rsync
echo ${PIPESTATUS[0]} >"${nsi_conn_done}"
} &
# while variables
rsync_copy_finish=0
rsync_progress=0
prev_progress=0
rsync_done=""
while [ "${rsync_copy_finish}" -eq 0 ]; do
# Sometimes reads the progress file while writing and only partial numbers (like 1 when is 15)
prev_progress=${rsync_progress}
rsync_progress=$(tail -n1 "${nsi_conn_progress}")
if [[ -z ${rsync_progress} ]]; then
rsync_progress=${prev_progress}
fi
if [ ${prev_progress} -gt ${rsync_progress} ]; then
rsync_progress=${prev_progress}
fi
echo "${rsync_progress}"
# finish the while if the rsync is finished
rsync_done=$(cat ${nsi_conn_done})
if [[ "${rsync_done}" != "no" ]]; then
if [[ ${rsync_done} -eq 0 ]]; then
rm -rf "${nsi_conn_path}"
rsync_copy_finish=1
else
# if rsync return error
echo "Error: could not copy rootfs files, exiting"
exit 4
fi
else
sleep 0.5
fi
done | \
dialog --backtitle "$backtitle" --title " $title " --gauge "\n\n Transferring rootfs to $2 ($USAGE MB). \n\n \
This will take approximately $(( $((USAGE/300)) * 1 )) minutes to finish. Please wait!\n\n" 11 80
# run rsync again to silently catch outstanding changes between / and "${TempDir}"/rootfs/
dialog --title "$title" --backtitle "$backtitle" --infobox "\n Cleaning up ... Almost done." 5 60
rsync -avrltD --delete --exclude-from=$EX_LIST / "${TempDir}"/rootfs >/dev/null 2>&1
# creating fstab from scratch
rm -f "${TempDir}"/rootfs/etc/fstab
mkdir -p "${TempDir}"/rootfs/etc "${TempDir}"/rootfs/media/mmcboot "${TempDir}"/rootfs/media/mmcroot
# Restore TMP and swap
echo "# <file system> <mount point> <type> <options> <dump> <pass>" > "${TempDir}"/rootfs/etc/fstab
echo "tmpfs /tmp tmpfs defaults,nosuid 0 0" >> "${TempDir}"/rootfs/etc/fstab
grep swap /etc/fstab >> "${TempDir}"/rootfs/etc/fstab
# creating fstab, kernel and boot script for NAND partition
#
if [[ $1 == *nand* ]]; then
echo "Finishing installation to NAND." >> $logfile
REMOVESDTXT="and remove SD to boot from NAND"
echo "$1 /boot vfat defaults 0 0" >> "${TempDir}"/rootfs/etc/fstab
echo "$2 / ext4 defaults,noatime,commit=600,errors=remount-ro 0 1" >> "${TempDir}"/rootfs/etc/fstab
dialog --title "$title" --backtitle "$backtitle" --infobox "\nConverting kernel ... few seconds." 5 60
mkimage -A arm -O linux -T kernel -C none -a "0x40008000" -e "0x40008000" -n "Linux kernel" -d \
/boot/zImage "${TempDir}"/bootfs/uImage >/dev/null 2>&1
cp /boot/script.bin "${TempDir}"/bootfs/
if [[ $DEVICE_TYPE != a13 ]]; then
# Note: Not using UUID based boot for NAND
cat <<-EOF > "${TempDir}"/bootfs/uEnv.txt
console=ttyS0,115200
root=$2 rootwait
extraargs="console=tty1 hdmi.audio=EDID:0 disp.screen0_output_mode=EDID:0 consoleblank=0 loglevel=1"
EOF
else
# Note: Not using UUID based boot for NAND
cat <<-EOF > "${TempDir}"/bootfs/uEnv.txt
console=ttyS0,115200
root=$2 rootwait
extraargs="consoleblank=0 loglevel=1"
EOF
fi
sync
[[ $DEVICE_TYPE = a20 ]] && echo "machid=10bb" >> "${TempDir}"/bootfs/uEnv.txt
# ugly hack becouse we don't have sources for A10 nand uboot
if [[ $ID == Cubieboard || $BOARD_NAME == Cubieboard || $ID == "Lime A10" || $BOARD_NAME == "Lime A10" ]]; then
cp "${TempDir}"/bootfs/uEnv.txt "${TempDir}"/rootfs/boot/uEnv.txt
cp "${TempDir}"/bootfs/script.bin "${TempDir}"/rootfs/boot/script.bin
cp "${TempDir}"/bootfs/uImage "${TempDir}"/rootfs/boot/uImage
fi
umount_device "/dev/nand"
tune2fs -o journal_data_writeback /dev/nand2 >/dev/null 2>&1
tune2fs -O ^has_journal /dev/nand2 >/dev/null 2>&1
e2fsck -f /dev/nand2 >/dev/null 2>&1
fi
# Boot from eMMC, root = eMMC or SATA / USB
#
if [[ ($2 == ${emmccheck}p* || $1 == ${emmccheck}p*) && $DEVICE_TYPE != uefi ]]; then
if [[ $2 == ${DISK_ROOT_PART} ]]; then
local targetuuid=$satauuid
local choosen_fs=$FilesystemChoosen
echo "Finalizing: boot from eMMC, rootfs on USB/SATA/NVMe." >> $logfile
if [[ $eMMCFilesystemChoosen =~ ^(btrfs|f2fs)$ ]]; then
echo "$emmcuuid /media/mmcroot $eMMCFilesystemChoosen ${mountopts[$eMMCFilesystemChoosen]}" >> "${TempDir}"/rootfs/etc/fstab
fi
else
local targetuuid=$emmcuuid
local choosen_fs=$eMMCFilesystemChoosen
echo "Finishing full install to eMMC." >> $logfile
fi
# fix that we can have one exlude file
cp -R /boot "${TempDir}"/bootfs
# old boot scripts
[[ -f "${TempDir}"/bootfs/boot/boot.cmd ]] && sed -e 's,root='"$root_uuid"',root='"$targetuuid"',g' -i "${TempDir}"/bootfs/boot/boot.cmd
# new boot scripts
if [[ -f "${TempDir}"/bootfs/boot/armbianEnv.txt ]]; then
sed -e 's,rootdev=.*,rootdev='"$targetuuid"',g' -i "${TempDir}"/bootfs/boot/armbianEnv.txt
grep -q '^rootdev' "${TempDir}"/bootfs/boot/armbianEnv.txt || echo "rootdev=$targetuuid" >> "${TempDir}"/bootfs/boot/armbianEnv.txt
else
[[ -f "${TempDir}"/bootfs/boot/boot.cmd ]] && sed -e 's,setenv rootdev.*,setenv rootdev '"$targetuuid"',g' -i "${TempDir}"/bootfs/boot/boot.cmd
[[ -f "${TempDir}"/bootfs/boot/boot.ini ]] && sed -e 's,^setenv rootdev.*$,setenv rootdev "'"$targetuuid"'",' -i "${TempDir}"/bootfs/boot/boot.ini
[[ -f "${TempDir}"/rootfs/boot/boot.ini ]] && sed -e 's,^setenv rootdev.*$,setenv rootdev "'"$targetuuid"'",' -i "${TempDir}"/rootfs/boot/boot.ini
fi
if [[ -f "${TempDir}"/bootfs/boot/extlinux/extlinux.conf ]]; then
sed -e 's,root='"$root_uuid"',root='"$targetuuid"',g' -i "${TempDir}"/bootfs/boot/extlinux/extlinux.conf
[[ -f "${TempDir}"/bootfs/boot/boot.cmd ]] && rm "${TempDir}"/bootfs/boot/boot.cmd
else
mkimage -C none -A arm -T script -d "${TempDir}"/bootfs/boot/boot.cmd "${TempDir}"/bootfs/boot/boot.scr >/dev/null 2>&1 || (echo 'Error while creating U-Boot loader image with mkimage' >&2 ; exit 5)
fi
# fstab adj
if [[ "$1" != "$2" ]]; then
echo "$emmcbootuuid /media/mmcboot ext4 ${mountopts[ext4]}" >> "${TempDir}"/rootfs/etc/fstab
echo "/media/mmcboot/boot /boot none bind 0 0" >> "${TempDir}"/rootfs/etc/fstab
fi
# if the rootfstype is not defined as cmdline argument on armbianEnv.txt
if ! grep -qE '^rootfstype=.*' "${TempDir}"/bootfs/boot/armbianEnv.txt; then
# Add the line of type of the selected rootfstype to the file armbianEnv.txt
[[ -f "${TempDir}"/bootfs/boot/armbianEnv.txt ]] && echo "rootfstype=$choosen_fs" >> "${TempDir}"/bootfs/boot/armbianEnv.txt
fi
if [[ $eMMCFilesystemChoosen =~ ^(btrfs|f2fs)$ ]]; then
echo "$targetuuid / $choosen_fs ${mountopts[$choosen_fs]}" >> "${TempDir}"/rootfs/etc/fstab
# swap file not supported under btrfs but we might have made a partition
[[ -n ${emmcswapuuid} ]] && sed -e 's,/var/swap.*,'$emmcswapuuid' none swap sw 0 0,g' -i "${TempDir}"/rootfs/etc/fstab
if [[ -f "${TempDir}"/bootfs/boot/armbianEnv.txt ]]; then
sed -e 's,rootfstype=.*,rootfstype='$eMMCFilesystemChoosen',g' -i "${TempDir}"/bootfs/boot/armbianEnv.txt
else
echo 'rootfstype='$eMMCFilesystemChoosen >>"${TempDir}"/bootfs/boot/armbianEnv.txt
fi
else
[[ -f "${TempDir}"/bootfs/boot/armbianEnv.txt ]] && sed -e 's,rootfstype=.*,rootfstype='$choosen_fs',g' -i "${TempDir}"/bootfs/boot/armbianEnv.txt
echo "$targetuuid / $choosen_fs ${mountopts[$choosen_fs]}" >> "${TempDir}"/rootfs/etc/fstab
fi
if [[ $(type -t write_uboot_platform) != function ]]; then
echo "Error: no u-boot package found, exiting"
exit 6
fi
write_uboot_platform "$DIR" $emmccheck
fi
# Boot from SD card, root = SATA / USB
#
if [[ $2 == ${DISK_ROOT_PART} && -z $1 && $DEVICE_TYPE != uefi ]]; then
echo -e "Finishing transfer to disk, boot from SD/eMMC" >> $logfile
[[ -f /boot/boot.cmd ]] && sed -e 's,root='"$root_uuid"',root='"$satauuid"',g' -i /boot/boot.cmd
[[ -f /boot/boot.ini ]] && sed -e 's,^setenv rootdev.*$,setenv rootdev "'"$satauuid"'",' -i /boot/boot.ini
# new boot scripts
if [[ -f /boot/armbianEnv.txt ]]; then
sed -e 's,rootdev=.*,rootdev='"$satauuid"',g' -i /boot/armbianEnv.txt
grep -q '^rootdev' /boot/armbianEnv.txt || echo "rootdev=$satauuid" >> /boot/armbianEnv.txt
sed -e 's,rootfstype=.*,rootfstype='$FilesystemChoosen',g' -i /boot/armbianEnv.txt
grep -q '^rootfstype' /boot/armbianEnv.txt || echo "rootfstype=$FilesystemChoosen" >> /boot/armbianEnv.txt
else
sed -e 's,setenv rootdev.*,setenv rootdev '"$satauuid"',' -i /boot/boot.cmd
sed -e 's,setenv rootdev.*,setenv rootdev '"$satauuid"',' -i /boot/boot.ini
sed -e 's,setenv rootfstype.*,setenv rootfstype '"$FilesystemChoosen"',' -i /boot/boot.cmd
sed -e 's,setenv rootfstype.*,setenv rootfstype '"$FilesystemChoosen"',' -i /boot/boot.ini
fi
if [[ -f /bootfs/boot/extlinux/extlinux.conf ]]; then
sed -e 's,root='"$root_uuid"',root='"$satauuid"',g' -i /boot/extlinux/extlinux.conf
[[ -f /boot/boot.cmd ]] && rm /boot/boot.cmd
fi
[[ -f /boot/boot.cmd ]] && mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr >/dev/null 2>&1 || (echo 'Error while creating U-Boot loader image with mkimage' >&2 ; exit 7)
mkdir -p "${TempDir}"/rootfs/media/mmc/boot
echo "${sduuid} /media/mmcboot ext4 ${mountopts[ext4]}" >> "${TempDir}"/rootfs/etc/fstab
echo "/media/mmcboot/boot /boot none bind 0 0" >> "${TempDir}"/rootfs/etc/fstab
echo "$satauuid / $FilesystemChoosen ${mountopts[$FilesystemChoosen]}" >> "${TempDir}"/rootfs/etc/fstab
# recreate swap file if already existing (might be missing since zram only)
if [ -f /var/swap ]; then
fallocate -l 128M "${TempDir}"/rootfs/var/swap || dd if=/dev/zero of="${TempDir}"/rootfs/var/swap bs=1M count=128 status=noxfer
mkswap "${TempDir}"/rootfs/var/swap
fi
fi
if [[ $2 == ${DISK_ROOT_PART} && -z $1 && $DEVICE_TYPE = uefi ]]; then
# create swap file size of your memory so we can use it for S4
MEM_TOTAL=$(cat /proc/meminfo | awk '/MemTotal/ {print $2}')
# but no more then 16Gb
[[ ${MEM_TOTAL} -gt 16107868 ]] && MEM_TOTAL=16107868
dd if=/dev/zero of="${TempDir}"/rootfs/swapfile bs=${MEM_TOTAL} count=1024 conv=notrunc >> $logfile
mkswap "${TempDir}"/rootfs/swapfile >> $logfile
chmod 0600 "${TempDir}"/rootfs/swapfile
sed -i "/^GRUB_CMDLINE_LINUX_DEFAULT=/ s/\"$/ resume=UUID=$(findmnt -no UUID -T "${TempDir}"/rootfs/swapfile) resume_offset=$(filefrag -v "${TempDir}"/rootfs/swapfile |grep " 0:"| awk '{print $4}' | cut -d"." -f1)\"/" "${TempDir}"/rootfs/etc/default/grub.d/98-armbian.cfg
echo "GRUB_DISABLE_OS_PROBER=false" >> "${TempDir}"/rootfs/etc/default/grub.d/98-armbian.cfg
echo "$satauuid / $FilesystemChoosen ${mountopts[$FilesystemChoosen]}" >> "${TempDir}"/rootfs/etc/fstab
echo "UUID=$(lsblk -io KNAME,LABEL,UUID,PARTLABEL | grep $diskcheck | grep -i efi | awk '{print $3}') /boot/efi vfat defaults 0 2" >> "${TempDir}"/rootfs/etc/fstab
echo "/swapfile none swap sw 0 0" >> "${TempDir}"/rootfs/etc/fstab
cat <<-hibernatemenu >"${TempDir}"/rootfs/etc/polkit-1/localauthority/50-local.d/com.ubuntu.enable-hibernate.pkla
[Re-enable hibernate by default in upower]
Identity=unix-user:*
Action=org.freedesktop.upower.hibernate
ResultActive=yes
[Re-enable hibernate by default in logind]
Identity=unix-user:*
Action=org.freedesktop.login1.hibernate;org.freedesktop.login1.handle-hibernate-key;org.freedesktop.login1;org.freedesktop.login1.hibernate-multiple-sessions;org.freedesktop.login1.hibernate-ignore-inhibit
ResultActive=yes
hibernatemenu
efi_partition=$(LC_ALL=C fdisk -l "/dev/$diskcheck" 2>/dev/null | grep "EFI" | awk '{print $1}')
echo "Install GRUB to $efi_partition"
mkdir -p "${TempDir}"/rootfs/{dev,proc,sys}
mount $efi_partition "${TempDir}"/rootfs/boot/efi
mount --bind /dev "${TempDir}"/rootfs/dev
mount --make-rslave --bind /dev/pts "${TempDir}"/rootfs/dev/pts
mount --bind /proc "${TempDir}"/rootfs/proc
mount --make-rslave --rbind /sys "${TempDir}"/rootfs/sys
arch_target=$([[ $(arch) == x86_64 ]] && echo "x86_64-efi" || echo "arm64-efi")
chroot "${TempDir}/rootfs/" /bin/bash -c "grub-install --target=$arch_target --efi-directory=/boot/efi --bootloader-id=Armbian" >> $logfile
chroot "${TempDir}/rootfs/" /bin/bash -c "grub-mkconfig -o /boot/grub/grub.cfg" >> $logfile
grep "${TempDir}"/rootfs/sys /proc/mounts | cut -f2 -d" " | sort -r | xargs umount -n
umount "${TempDir}"/rootfs/proc
umount "${TempDir}"/rootfs/dev/pts
umount "${TempDir}"/rootfs/dev
umount "${TempDir}"/rootfs/boot/efi
fi
# Boot from MTD flash, root = SATA / USB
#
if [[ $1 == *mtd* ]]; then
if [[ -f "${TempDir}"/rootfs/boot/armbianEnv.txt ]]; then
sed -e 's,rootdev=.*,rootdev='"$satauuid"',g' -i "${TempDir}"/rootfs/boot/armbianEnv.txt
fi
if [[ -f "${TempDir}"/rootfs/boot/extlinux/extlinux.conf ]]; then
sed -e 's,root='"$root_uuid"',root='"$satauuid"',g' -i "${TempDir}"/rootfs/boot/extlinux/extlinux.conf
fi
echo "$satauuid / $FilesystemChoosen ${mountopts[$FilesystemChoosen]}" >> "${TempDir}"/rootfs/etc/fstab
fi
# recreate OMV mounts at destination if needed
grep -q ' /srv/' /etc/fstab
if [ $? -eq 0 -a -f /etc/default/openmediavault ]; then
echo -e '# >>> [openmediavault]' >> "${TempDir}"/rootfs/etc/fstab
grep ' /srv/' /etc/fstab | while read ; do
echo "${REPLY}" >> "${TempDir}"/rootfs/etc/fstab
mkdir -p -m700 "${TempDir}/rootfs$(awk -F" " '{print $2}' <<<"${REPLY}")"
done
echo -e '# <<< [openmediavault]' >> "${TempDir}"/rootfs/etc/fstab
fi
echo -e "\nChecking again for open files:" >> $logfile
lsof / | awk 'NR==1 || $4~/[0-9][uw]/' | grep -v "^COMMAND" >> $logfile
LANG=C echo -e "\n$(date): Finished\n\n" >> $logfile
cat $logfile > "${TempDir}"/rootfs${logfile}
sync
umount "${TempDir}"/rootfs
mountpoint -q "${TempDir}"/bootfs && umount "${TempDir}"/bootfs
} # create_armbian
# Accept device as parameter: for example /dev/sda unmounts all their mounts
umount_device()
{
if [[ -n $1 ]]; then
device="$1";
for n in ${device}*; do
if [[ $device != "$n" ]]; then
if mount|grep -q "$n"; then
umount -l "$n" >/dev/null 2>&1
fi
fi
done
fi
} # umount_device
show_nand_warning()
{
local temp_rc=$(mktemp)
cat <<-'EOF' > $temp_rc
screen_color = (WHITE,RED,ON)
EOF
local warn_text="You are installing the system to sunxi NAND.
This is not recommended as NAND has \Z1worse performance
and reliability\Zn than a good SD card.
You have been warned."
DIALOGRC=$temp_rc dialog --title "NAND warning" --backtitle "$backtitle" --colors \
--ok-label "I understand and agree" --msgbox "$warn_text" 10 70
}
# formatting sunxi NAND - no parameters, fixed solution.
#
format_nand()
{
[[ ! -e /dev/nand ]] && echo '/dev/nand does not exist' >&2 && exit 8
show_nand_warning
dialog --title "$title" --backtitle "$backtitle" --infobox "\n Formatting ... up to one minute." 5 60
if [[ $DEVICE_TYPE = a20 ]]; then
(echo y;) | sunxi-nand-part -f a20 /dev/nand 65536 'bootloader 65536' 'linux 0' >> $logfile 2>&1
else
(echo y;) | sunxi-nand-part -f a10 /dev/nand 65536 'bootloader 65536' 'linux 0' >> $logfile 2>&1
fi
mkfs.vfat /dev/nand1 >> $logfile 2>&1
mkfs.ext4 -qF /dev/nand2 >> $logfile 2>&1
}
# formatting eMMC [device] example /dev/mmcblk1 - one can select filesystem type
#
format_emmc()
{
# choose and create fs
IFS=" "
BTRFS=$(grep -o btrfs /proc/filesystems)
FilesystemTargets="1 ext4 2 f2fs"
[[ -n $BTRFS && ! `uname -r | grep '^3.' ` ]] && FilesystemTargets=$FilesystemTargets" 3 $BTRFS"
FilesystemOptions=($FilesystemTargets)
FilesystemCmd=(dialog --title "Select filesystem type for eMMC $1" --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
FilesystemChoices=$("${FilesystemCmd[@]}" "${FilesystemOptions[@]}" 2>&1 >/dev/tty)
[[ $? -ne 0 ]] && exit 9
eMMCFilesystemChoosen=${FilesystemOptions[(2*$FilesystemChoices)-1]}
# deletes all partitions on eMMC drive
dd bs=1 seek=446 count=64 if=/dev/zero of="$1" >/dev/null 2>&1
# calculate capacity and reserve some unused space to ease cloning of the installation
# to other media 'of the same size' (one sector less and cloning will fail)
QUOTED_DEVICE=$(echo "$1" | sed 's:/:\\\/:g')
CAPACITY=$(parted "$1" unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", \$2 / ( 1024 / \$4 ))}")
# We use 16MiB to align partitions which may overestimate the erase block
# size of a NAND device. Overestimating is harmless. (512 byte
# sectors, so we use 32768 as divider and substract 1)
if [[ $CAPACITY -lt 4000000 ]]; then
# Leave 2 percent unpartitioned when eMMC size is less than 4GB (unlikely)
LASTSECTOR=$(( 32768 * $(parted "$1" unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 98 / 3276800))}") -1 ))
else
# Leave 1 percent unpartitioned
LASTSECTOR=$(( 32768 * $(parted "$1" unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 99 / 3276800))}") -1 ))
fi
# get target partition table type from the root partition device
PART_TABLE_TYPE=$(parted "$root_partition_device" print -sm | awk -F ":" -v pattern="$root_partition_device" '$0 ~ pattern {print $6}')
parted -s "$1" -- mklabel "$PART_TABLE_TYPE"
dialog --title "$title" --backtitle "$backtitle" --infobox "\nFormating $1 to $eMMCFilesystemChoosen ... please wait." 5 60
# we can't boot from btrfs or f2fs
if [[ $eMMCFilesystemChoosen =~ ^(btrfs|f2fs)$ ]]; then
local partedFsType="${eMMCFilesystemChoosen}"
if [[ $eMMCFilesystemChoosen == "f2fs" ]]; then
partedFsType=''
fi
# default boot partition size, in MiB
DEFAULT_BOOTSIZE=256
# (convert to sectors for partitioning)
DEFAULT_BOOTSIZE_SECTORS=$(((${DEFAULT_BOOTSIZE} * 1024 * 1024) / 512))
# check if the filesystem tools are actually installed
if ! command -v mkfs.${eMMCFilesystemChoosen} >/dev/null 2>&1; then
echo "Error: Filesystem tools for ${eMMCFilesystemChoosen} not installed, exiting"
exit 9
fi
# check whether swap is currently defined and a new swap partition is needed
grep -q swap /etc/fstab
case $? in
0)
parted -s "$1" -- mkpart primary $partedFsType ${FIRSTSECTOR}s $(( ${FIRSTSECTOR} + ${DEFAULT_BOOTSIZE_SECTORS} - 1 ))s
parted -s "$1" -- mkpart primary $partedFsType $(( ${FIRSTSECTOR} + ${DEFAULT_BOOTSIZE_SECTORS} ))s $(( ${FIRSTSECTOR} + 393215 ))s
parted -s "$1" -- mkpart primary $partedFsType $(( ${FIRSTSECTOR} + 393216 ))s ${LASTSECTOR}s
partprobe "$1"
mkfs.ext4 ${mkopts[ext4]} "$1"'p1' >> $logfile 2>&1
mkswap "$1"'p2' >> $logfile 2>&1
mkfs.${eMMCFilesystemChoosen} "$1"'p3' ${mkopts[$eMMCFilesystemChoosen]} >> $logfile 2>&1
emmcbootuuid=$(blkid -o export "$1"'p1' | grep -w UUID)
emmcswapuuid=$(blkid -o export "$1"'p2' | grep -w UUID)
emmcuuid=$(blkid -o export "$1"'p3' | grep -w UUID)
dest_root=$emmccheck'p3'
;;
*)
parted -s "$1" -- mkpart primary $partedFsType ${FIRSTSECTOR}s $(( ${FIRSTSECTOR} + ${DEFAULT_BOOTSIZE_SECTORS} - 1 ))s
parted -s "$1" -- mkpart primary $partedFsType $(( ${FIRSTSECTOR} + ${DEFAULT_BOOTSIZE_SECTORS} ))s ${LASTSECTOR}s
partprobe "$1"
mkfs.ext4 ${mkopts[ext4]} "$1"'p1' >> $logfile 2>&1
mkfs.${eMMCFilesystemChoosen} "$1"'p2' ${mkopts[$eMMCFilesystemChoosen]} >> $logfile 2>&1
emmcbootuuid=$(blkid -o export "$1"'p1' | grep -w UUID)
emmcuuid=$(blkid -o export "$1"'p2' | grep -w UUID)
dest_root=$emmccheck'p2'
;;
esac
else
parted -s "$1" -- mkpart primary $eMMCFilesystemChoosen ${FIRSTSECTOR}s ${LASTSECTOR}s
partprobe "$1"
mkfs.${eMMCFilesystemChoosen} ${mkopts[$eMMCFilesystemChoosen]} "$1"'p1' >> $logfile 2>&1
emmcuuid=$(blkid -o export "$1"'p1' | grep -w UUID)
emmcbootuuid=$emmcuuid
fi
}
# formatting SATA/USB/NVMe partition, examples: /dev/sda3 or /dev/nvme0n1p1
#
format_disk()
{
# choose and create fs
IFS=" "
ROOTFSTYPE=$(lsblk -o MOUNTPOINT,FSTYPE | awk -F" " '/^\/\ / {print $2}')
case ${ROOTFSTYPE} in
btrfs)
FilesystemTargets='1 btrfs'
;;
*)
BTRFS=$(grep -o btrfs /proc/filesystems)
FilesystemTargets='1 ext4'
[[ -n $BTRFS && ! `uname -r | grep '^3.' ` && $choice != 6 ]] && FilesystemTargets=$FilesystemTargets" 2 $BTRFS"
;;
esac
FilesystemOptions=($FilesystemTargets)
FilesystemCmd=(dialog --title "Select filesystem type for $1" --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
FilesystemChoices=$("${FilesystemCmd[@]}" "${FilesystemOptions[@]}" 2>&1 >/dev/tty)
[[ $? -ne 0 ]] && exit 10
FilesystemChoosen=${FilesystemOptions[(2*$FilesystemChoices)-1]}
dialog --title "$title" --backtitle "$backtitle" --infobox "\nFormating $1 to $FilesystemChoosen ... please wait." 5 60
mkfs.${FilesystemChoosen} ${mkopts[$FilesystemChoosen]} "$1" >> $logfile 2>&1
}
# choose target SATA/USB/NVMe partition.
check_partitions()
{
IFS=" "
[[ -n "$1" ]] && EXCLUDE=" | grep -v $1"
[[ -n "$2" ]] && INCLUDE=" | grep $2" && diskcheck=$2
CMD="lsblk -io KNAME,FSTYPE,SIZE,TYPE,MOUNTPOINT | grep -v -w $root_partition_name $INCLUDE $EXCLUDE | grep -E '^sd|^nvme|^md|^mmc' | awk -F\" \" '/ part | raid..? / {print \$1}'"
AvailablePartitions=$(eval $CMD)
if [[ -z $AvailablePartitions ]]; then
# Consider brand new devices or devices with a wiped partition table
if [[ -z $(blkid /dev/$diskcheck) ]]; then
# There is not yet any partition table on the disk device.
# => we have to calc the size in GB directly from the device.
FREE_SPACE=$(echo "scale=0; $(blockdev --getsize64 /dev/$diskcheck)/1024^3" | bc -l)
else
# The device has an initial partition table
FREE_SPACE=$(parted /dev/$diskcheck unit GB print free | awk '/Free Space/{c++; sum += $3; print sum}' | tail -1)
fi
# Logic for auto created partitions:
# 1. Check for a minimum free space of 4GB for a partition
# 2. Ask user to proceed with auto-created partition(s) or not
# 3. Distinguish between UEFI and non UEFI device
# 4. Create partition of full free size for a non UEFI device
#
if [[ "${FREE_SPACE%.*}" -lt 4 ]]; then
dialog --ok-label 'Exit' --title ' Warning ' --backtitle "$backtitle" --colors --no-collapse --msgbox "\n\Z1There is not enough free capacity on /dev/$diskcheck. Please check your device.\Zn" 7 52
exit 11
fi
dialog --yes-label "Proceed" --no-label 'Exit' --title "$title" --backtitle "$backtitle" --yesno "\nDestination $diskcheck has ${FREE_SPACE}GB of available space. \n\nAutomated install will generate needed partition(s)!" 9 55
[[ $? -ne 0 ]] && exit 11
if [[ "$DEVICE_TYPE" == uefi ]]; then
if [[ -z "$efi_partition" ]]; then
wipefs -aq /dev/$diskcheck
# create EFI partition
{
echo n; echo ; echo ; echo ; echo +200M;
echo t; echo EF; echo w;
} | fdisk /dev/$diskcheck &> /dev/null || true
yes | mkfs.vfat /dev/${diskcheck}p1 &> /dev/null || true
fatlabel /dev/${diskcheck}p1 EFI
fi
{
echo n; echo ; echo ; echo ; echo
echo w
} | fdisk /dev/$diskcheck &> /dev/null || true
yes | mkfs.ext4 /dev/${diskcheck}p2 &> /dev/null || true
# re-read
emmccheck=$(ls -d -1 /dev/mmcblk* 2>/dev/null | grep -w 'mmcblk[0-9]' | grep -v "$root_partition_device");
efi_partition=$(LC_ALL=C fdisk -l "/dev/$diskcheck" 2>/dev/null | grep "EFI" | awk '{print $1}')
else
# Create new partition of max free size
{
echo n; echo ; echo ; echo ; echo
echo w
} | fdisk /dev/$diskcheck &> /dev/null || true
fi
fi
CMD="lsblk -io KNAME,FSTYPE,SIZE,TYPE,MOUNTPOINT | grep -v -w $root_partition_name $INCLUDE $EXCLUDE | grep -E '^sd|^nvme|^md|^mmc' | awk -F\" \" '/ part | raid..? / {print \$1}' | uniq | sed 's|^|/dev/|' | nl | xargs echo -n"
partprobe
AvailablePartitions=$(eval $CMD)
PartitionOptions=($AvailablePartitions)
PartitionCmd=(dialog --title 'Select the destination:' --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
PartitionChoices=$("${PartitionCmd[@]}" "${PartitionOptions[@]}" 2>&1 >/dev/tty)
[[ $? -ne 0 ]] && exit 11
DISK_ROOT_PART=${PartitionOptions[(2*$PartitionChoices)-1]}
}
# build and update new bootscript
update_bootscript()
{
if [ -f /boot/boot.cmd.new ]; then
mv -f /boot/boot.cmd.new /boot/boot.cmd >/dev/null 2>&1
mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr >/dev/null 2>&1
elif [ -f /boot/boot.ini.new ]; then
mv -f /boot/boot.ini.new /boot/boot.ini >/dev/null 2>&1
rootdev=$(sed -e 's/^.*root=//' -e 's/ .*$//' < /proc/cmdline)
rootfstype=$(sed -e 's/^.*rootfstype=//' -e 's/ .*$//' < /proc/cmdline)
sed -i "s/setenv rootfstype.*/setenv rootfstype \"$rootfstype\"/" /boot/boot.ini
sed -i "s/setenv rootdev.*/setenv rootdev \"$rootdev\"/" /boot/boot.ini
fi
}
# show warning [TEXT]
show_warning()
{
dialog --title "$title" --backtitle "$backtitle" --cr-wrap --colors --yesno " \Z1$(toilet -W -f ascii9 ' WARNING')\Zn\n$1" 16 67
[[ $? -ne 0 ]] && exit 13
}
# try to stop running services
stop_running_services()
{
systemctl --state=running | awk -F" " '/.service/ {print $1}' | sort -r | \
grep -E -e "$1" | while read ; do
echo -e "\nStopping ${REPLY} \c"
systemctl stop ${REPLY} 2>&1
done
}
# show warning and write u-boot to MTD device(s)
# $1 = u-boot files directory
# $2 = space separated list of all MTD block and/or MTD char device partitions
write_uboot_to_mtd_flash()
{
local DIR="$1"
local MTD_ALL_DEVICE_PARTITIONS="$2"
# For backward compatibility to existing implementations of function write_uboot_platform_mtd
# we have to provide the first device as a dedicated device path:
local MTD_DEFAULT_DEVICE_PATH="/dev/${MTD_ALL_DEVICE_PARTITIONS%% *}"
# If the first device is a char device partition, it contains a :colon:
# -> so we have to take the part before the colon only
MTD_DEFAULT_DEVICE_PATH="${MTD_DEFAULT_DEVICE_PATH%%:*}"
local MESSAGE="This script will update the bootloader on one or multiple of these MTD devices:\n[ $MTD_ALL_DEVICE_PARTITIONS ]\n\nIt may take up to a few minutes - Continue?"
dialog --title "$title" --backtitle "$backtitle" --cr-wrap --colors --yesno " \Z1$(toilet -W -f ascii9 ' WARNING')\Zn\n$MESSAGE" 19 67
if [[ $? -eq 0 ]]; then
write_uboot_platform_mtd "$DIR" "$MTD_DEFAULT_DEVICE_PATH" "$logfile" "$MTD_ALL_DEVICE_PARTITIONS"
update_bootscript
echo 'Done'
fi
}
main()
{
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# This tool must run under root
if [[ $EUID -ne 0 ]]; then
echo 'This tool must run as root. Exiting ...' >&2
exit 14
fi
[ -f $logfile ] && echo -e '\n\n\n' >> $logfile
LANG=C echo -e "$(date): Start ${0##*/}.\n" >> $logfile
IFS="'"
options=()
if [[ -n $emmccheck ]]; then
ichip='eMMC';
dest_boot=$emmccheck'p1'
dest_root=$emmccheck'p1'
else
ichip='legacy SUNXI NAND'
dest_boot='/dev/nand1'
dest_root='/dev/nand2'
fi
if [[ -n $diskcheck && -d /sys/firmware/efi ]]; then
while read line
do
options+=("$line" "Install UEFI system with Grub")
done <<< "$diskcheck"
else
[[ -n $sduuid && -n $diskcheck ]] && options+=(1 'Boot from SD - system on SATA, USB or NVMe')
[[ -n $emmccheck ]] && options+=(2 "Boot from $ichip - system on $ichip")
[[ -n $emmccheck && -n $diskcheck ]] && options+=(3 "Boot from $ichip - system on SATA, USB or NVMe")
[[ -n $mtdcheck ]] && options+=(4 'Boot from MTD Flash - system on SATA, USB or NVMe')
[[ -n ${root_partition_device} && ${DEVICE_TYPE} != "uefi" ]] && options+=(5 'Install/Update the bootloader on SD/eMMC')
[[ ( $LINUXFAMILY == odroidxu4 || $LINUXFAMILY == mvebu* \
|| $LINUXFAMILY == mt7623 ) && \
( -b /dev/mmcblk0boot0 || -b /dev/mmcblk1boot0 ) ]] && options+=(6 'Install/Update the bootloader on special eMMC partition')
[[ -n $mtdcheck && \
$(type -t write_uboot_platform_mtd) == function ]] && options+=(7 'Install/Update the bootloader on MTD Flash')
fi
[[ ${#options[@]} -eq 0 || "$root_uuid" == "$emmcuuid" || "$root_uuid" == "/dev/nand2" ]] && \
dialog --ok-label 'Cancel' --title ' Warning ' --backtitle "$backtitle" --colors --no-collapse --msgbox '\n\Z1There are no targets. Please check your drives.\Zn' 7 52
cmd=(dialog --title 'Choose an option:' --backtitle "$backtitle" --menu "\nCurrent root: $root_uuid \n \n" 14 60 7)
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ $? -ne 0 ]] && exit 16
for choice in $choices
do
case $choice in
1)
title='MMC (SD/eMMC) boot | USB/SATA/NVMe root install'
command='Reboot'
check_partitions
show_warning "This script will erase your device $DISK_ROOT_PART. Continue?"
format_disk "$DISK_ROOT_PART"
create_armbian "" "$DISK_ROOT_PART"
;;
2)
title="$ichip install"
command='Power off'
show_warning "This script will erase your $ichip. Continue?"
if [[ -n $emmccheck ]]; then
umount_device "$emmccheck"
format_emmc "$emmccheck"
else
umount_device '/dev/nand'
format_nand
fi
create_armbian "$dest_boot" "$dest_root"
;;
3)
title="$ichip boot | USB/SATA/NVMe root install"
command='Power off'
check_partitions
show_warning "This script will erase your $ichip and $DISK_ROOT_PART. Continue?"
if [[ -n $emmccheck ]]; then
umount_device "$emmccheck"
format_emmc "$emmccheck"
else
umount_device '/dev/nand'
format_nand
fi
umount_device "${DISK_ROOT_PART//[0-9]*/}"
format_disk "$DISK_ROOT_PART"
create_armbian "$dest_boot" "$DISK_ROOT_PART"
;;
4)
# Espressobin has flash boot by default
title='MTD Flash boot | USB/SATA/NVMe root install'
command='Power off'
# we need to copy boot
sed -i '/boot/d' $EX_LIST
check_partitions
show_warning "This script will erase your device $DISK_ROOT_PART. Continue?"
format_disk "$DISK_ROOT_PART"
create_armbian 'mtd' "$DISK_ROOT_PART"
if [[ $(type -t write_uboot_platform_mtd) == function ]]; then
dialog --title "$title" --backtitle "$backtitle" --yesno \
"Do you want to write the bootloader to MTD Flash?\n\nIt is required if you have not done it before or if you have some non-Armbian bootloader in this flash." 8 60
if [[ $? -eq 0 ]]; then
write_uboot_to_mtd_flash "$DIR" "$mtdcheck"
fi
fi
;;
5)
show_warning 'This script will update the bootloader on SD/eMMC. Continue?'
write_uboot_platform "$DIR" "${root_partition_device}"
update_bootscript
dialog --backtitle "$backtitle" --title 'Writing bootloader' --msgbox '\n Done.' 7 30
return
;;
6)
if [[ -b /dev/mmcblk0boot0 ]]; then
BOOTPART='/dev/mmcblk0'
elif [[ -b /dev/mmcblk1boot0 ]]; then
BOOTPART='/dev/mmcblk1'
fi
show_warning "This script will update the bootloader on $BOOTPART. Continue?"
write_uboot_platform "$DIR" $BOOTPART
echo 'Done'
return
;;
7)
write_uboot_to_mtd_flash "$DIR" "$mtdcheck"
return
;;
*)
title='UEFI install to internal drive'
command='Reboot'
check_partitions "$root_partition_device_name" "$choice"
# we need to copy boot
sed -i '/boot/d' $EX_LIST
show_warning "This script will erase your device $DISK_ROOT_PART. Continue?"
format_disk "$DISK_ROOT_PART"
create_armbian "" "$DISK_ROOT_PART" "$choice"
;;
esac
done
dialog --title "$title" --backtitle "$backtitle" --yes-label "$command" --no-label 'Exit' --yesno "\nAll done. $command $REMOVESDTXT" 7 70
[[ $? -eq 0 ]] && "$(echo ${command,,} | sed 's/ //')"
} # main
main "$@"

269
packages/bsp/common/usr/sbin/ddbr Executable file
View File

@@ -0,0 +1,269 @@
#!/bin/bash
# Author: xXx
# Purpose: Automate the process of backing up internal storage.
# Date: 4 Jan 2017 20:22:00 EET
###############################################################################
# Update: 5 Jan 2017 19:48:00 EET #
# Reason: Added support for when the user have started his machine #
# from USB. Now the right source and destination should be selected. #
# Added support for uncompressed images. #
# Added detection if the user runs already from emmc. #
###############################################################################
# Update: 6 Jan 2017 21:43:00 EET #
# Reason: Added functionality to restore images that this program creates. #
###############################################################################
# Update: 8 Mar 2017 18:30:00 EET #
# Reason: Changed yellow color to cyan for white backround terminals. #
###############################################################################
# Update: 8 Mar 2017 18:52:00 EET #
# Reason: Changed backup/restore dir to /ddbr as installer excludes this dir. #
###############################################################################
# Update: 12 Mar 2017 10:47:00 EET #
# Reason: Added the ability for the user to continue with compressed backup #
# only, and at his/her own risk, in case of lesser free space on the drive. #
# Tried to annoy the user with questions, in order to discourage him/her. #
###############################################################################
# Update: 12 Mar 2017 13:02:00 EET #
# Reason: Separated backup and restore dialogs for better handling of the #
# various situations for the program itself. Now the program ask first if a #
# backup or restore is wanted, and skips/adds some checks accordingly. #
# There should be no stops now, if a restore only wanted, and the free space #
# was too low, as this is irrelevant to the requested function. #
###############################################################################
# Update: 12 Mar 2017 16:08:00 EET #
# Reason: The program can now accept an argument for PowerUsers. #
# This argument can only be a directory, and must exists before calling the #
# program. This mode is dangerous, and most users will not need this mode, as #
# great damages can be done to your system if you use it incorrectly. #
# The argument is really the backup/restore directory that now can be forced #
# by the user, to bypass the programs checks, always at his/her own risk. #
###############################################################################
# Update: 12 Mar 2017 16:32:00 EET #
# Reason: Code cleaning. As the program have become very complex already, a #
# cleaner code was mandatory, in order to keep it safe and maintainable. If i #
# am to kill any bugs below these lines, i should be able to spot them first. #
###############################################################################
# Update: 13 Mar 2017 11:52:00 EET #
# Reason: Squashed some small bugs when running on normal Linux desktops that #
# have no EMMC or SDCARDS installed. And some more code cleaning. #
###############################################################################
# Update: 13 Mar 2017 12:40:00 EET #
# Reason: Changed the messages to darker colors for better compatibility with #
# white background terminals. Only the red color is now bright for emphasis. #
###############################################################################
_r=$(tput bold && tput setaf 1)
_g=$(tput setaf 2)
_b=$(tput setaf 4)
_c=$(tput setaf 6)
_x=$(tput sgr0)
[ $(whoami) != root ] && echo "$_r Please run this program as root""$_x" && exit 1
OUTDIR=$1
if [ "$OUTDIR" = "" ]
then
OUTDIR="/ddbr"
[ ! -d /ddbr ] && mkdir -p /ddbr
else
OUTDIR=$(echo "$OUTDIR" | sed "s,/\+$,,")
echo "$_b ARGUMENT MODE DETECTED. YOU HAVE BEEN WARNED!!! $_x"
echo "$_b NO IN/OUT SIZE CHECKS WILL BE PERFORMED IN THIS MODE. $_x"
echo "$_b YOU ARE USING THIS MODE AT YOUR OWN RISK!!! $_x"
if [ ! -d "$OUTDIR" ]
then
echo "$_r IN ARGUMENT MODE THE OUT/IN DIRECTORY MUST PRE-EXIST $_x"
echo "$_r AND IT IS BETTER TO BE ON AN MOUNTED EXTERNAL DRIVE. $_x"
echo "$_r PROGRAM EXITED DUE TO ERROR: NO DIR $OUTDIR $_x"
exit 1
fi
fi
dobackup(){
echo $_c" DO YOU WANT COMPRESSION ? "$_x
while true
read -p " "$_b"YES=("$_c"y"$_b") NO=("$_c"n"$_b")"$_x" " yn
do
case $yn in
y)
COMPRESS=TRUE
break;;
n)
COMPRESS=FALSE
break;;
*)
;;
esac
done
if [ "$COMPRESS" = "TRUE" ]
then
echo "$_b SAVING AND COMPRESSING "$_g"$emmc"$_b" TO "$_g"$OUTDIR/$image.gz"$_x"..."
dd if=/dev/$emmc | pv -s $intsize"K" | gzip > $OUTDIR/$image.gz
finish
else
echo "$_b SAVING "$_g"$emmc"$_b" TO "$_g"$OUTDIR/$image"$_x"..."
dd if=/dev/$emmc | pv -s $intsize"K" | dd of=$OUTDIR/$image
finish
fi
}
dorestore(){
echo $_c" DID YOU USED COMPRESSION WHEN YOU TOOK THE BACKUP ? "$_x
while true
read -p " "$_b"YES=("$_c"y"$_b") NO=("$_c"n"$_b")"$_x" " yn
do
case $yn in
y)
COMPRESS=TRUE
break;;
n)
COMPRESS=FALSE
break;;
*)
;;
esac
done
if [ "$COMPRESS" = "TRUE" ]
then
[ ! -f $OUTDIR/$image.gz ] && echo "$_r NO IMAGE FOUND. MAKE SURE YOU HAVE MADE A BACKUP FIRST."$_x"" && exit 1
echo "$_c YOU ARE ABOUT TO MAKE SERIOUS CHANGES TO YOUR SYSTEM!!!"
echo " FILE "$_g"$OUTDIR/$image.gz"$_c" IS GOING TO BE WRITEN TO "$_g"$emmc"$_c" "
echo " MAKE SURE EVERYTHING LOOKS OK AND:"
read -p " PRESS ENTER TO CONTINUE OR CTRL+C TO CANCEL $_x" blah
echo $_b" RESTORING $OUTDIR/$image.gz TO /dev/$emmc | PLEASE WAIT..."$_x
gunzip -c $OUTDIR/$image.gz | pv -s $intsize"K" | dd of=/dev/$emmc
finish
else
[ ! -f $OUTDIR/$image ] && echo "$_r NO IMAGE FOUND. MAKE SURE YOU HAVE MADE A BACKUP FIRST."$_x"" && exit 1
echo "$_c YOU ARE ABOUT TO MAKE SERIOUS CHANGES TO YOUR SYSTEM!!!"
echo " FILE "$_g"$OUTDIR/$image"$_c" IS GOING TO BE WRITEN TO "$_g"$emmc"$_c" "
echo " MAKE SURE EVERYTHING LOOKS OK AND:"
read -p " PRESS ENTER TO CONTINUE OR CTRL+C TO CANCEL $_x" blah
echo $_b" RESTORING $OUTDIR/$image TO /dev/$emmc | PLEASE WAIT..."$_x
dd if=$OUTDIR/$image | pv -s $intsize"K" | dd of=/dev/$emmc
finish
fi
}
compress(){
echo "$_c YOU ARE IN FORCED COMPRESSION MODE!!! $_x"
echo " THIS MODE CAN BE FROM DANGEROUS TO DESTRUCTIVE FOR YOUR $runfrom DRIVE"
echo " IF THE COMPRESSED BACKUP GROW BIGGER THAN THE FREE SPACE ON THE DRIVE"
echo " BAD THINGS MAY HAPPEN TO YOUR CURRENTLY RUNNING DRIVE $runfrom"
echo " IT IS BETTER TO USE A DRIVE WITH PLENTY OF SPACE FOR BACKING UP EMMC"
echo " BY PRESSING ENTER YOU ARE CONTINUING AT YOUR OWN RISK!!!"
read -p " CTRL+C to QUIT | ENTER TO CONTINUE " null
while true
read -p " "$_b"ARE YOU SURE? YES=("$_c"y"$_b") NO=("$_c"n"$_b")"$_x" " YN
do
case $YN in
y)
break;;
n)
exit 1
break;;
*)
;;
esac
done
echo "$_b SAVING AND COMPRESSING "$_g"$emmc"$_b" TO "$_g"$OUTDIR/$image.gz"$_x"..."
dd if=/dev/$emmc | pv -s $intsize"K" | gzip > $OUTDIR/$image.gz
finish
}
finish(){
echo "$_g JOB FINISHED!"$_x""
exit 0
}
echo "$_c DO YOU WANT TO BACKUP OR RESTORE ? "$_x""
while true
read -p " "$_b"BACKUP=("$_c"b"$_b") RESTORE=("$_c"r"$_b")"$_x" " br
do
case $br in
b)
wantsbackup=true
break;;
r)
wantsbackup=false
break;;
*)
;;
esac
done
### COMMON CHECKS / VARIABLES CREATION / INFO GATHERING
hasdrives=$(lsblk | grep -oE '(mmcblk[0-9])' | sort | uniq)
if [ "$hasdrives" = "" ]
then
echo "$_r UNABLE TO FIND ANY EMMC OR SD DRIVES ON THIS SYSTEM!!! $_x"
exit 1
fi
avail=$(lsblk | grep -oE '(mmcblk[0-9]|sda[0-9])' | sort | uniq)
if [ "$avail" = "" ]
then
echo "$_r UNABLE TO FIND ANY DRIVES ON THIS SYSTEM!!! $_x"
exit 1
fi
runfrom=$(lsblk | grep / | grep -oE '(mmcblk[0-9]|sda[0-9])')
if [ "$runfrom" = "" ]
then
echo "$_r UNABLE TO FIND ROOT OF THE RUNNING SYSTEM!!! $_x"
exit 1
fi
emmc=$(echo $avail | sed "s/$runfrom//" | sed "s/sd[a-z][0-9]//g" | sed "s/ //g")
if [ "$emmc" = "" ]
then
echo "$_r UNABLE TO FIND YOUR EMMC DRIVE "$_c"OR"$_r" YOU ALREADY RUN FROM EMMC!!! $_x"
exit 1
fi
if [ "$runfrom" = "$avail" ]
then
echo "$_r YOU ARE RUNNING ALREADY FROM EMMC!!! $_x"
exit 1
fi
if [ $runfrom = $emmc ]
then
echo "$_r YOU ARE RUNNING ALREADY FROM EMMC!!! $_x"
exit 1
fi
if [ "$(echo $emmc | grep mmcblk)" = "" ]
then
echo "$_r YOU DO NOT APPEAR TO HAVE AN EMMC DRIVE!!! $_x"
exit 1
fi
intsize=$(fdisk -s /dev/$emmc)
#image=$(echo $(grep -E '(Hardware|Revision)' /proc/cpuinfo | awk '{print $3}') | sed "s/ /-/g")-emmc.img
image=BACKUP-arm-64-emmc.img
### BACKUP ONLY CHECKS
if [ "$wantsbackup" = true ]
then
rootfree=$(df | grep /$ | awk '{print $4}')
[ $rootfree -le $intsize ] && echo -e "$_r NOT ENOUGH FREE SPACE! \n FORCING COMPRESSION MODE $_x" && compress=true
else
echo "$_b AVAILABLE DEVICES: "$_g"$(echo $avail)""$_x"
echo "$_b YOU ARE RUNNING "$_g"$(lsb_release -c | awk '{print $2}')"$_b" FROM "$_g"$runfrom""$_x"
dorestore
fi
echo "$_b AVAILABLE DEVICES: "$_g"$(echo $avail)""$_x"
echo "$_b YOU ARE RUNNING "$_g"$(lsb_release -c | awk '{print $2}')"$_b" FROM "$_g"$runfrom""$_x"
if [ $(echo $intsize | sed "s/ //g" | wc -c) -le 7 ]
then
echo -e "$_b INTERNAL EMMC IS: "$_g"$emmc"$_b" SIZE:\t"$_g"$intsize""$_x"
else
echo -e "$_b INTERNAL EMMC IS: "$_g"$emmc"$_b" SIZE:\t"$_g"$intsize""$_x"
fi
if [ $(echo $rootfree | sed "s/ //g" | wc -c) -le 7 ]
then
echo -e "$_b ROOT ($runfrom) FREE SPACE IS:\t\t\t"$_g"$rootfree""$_x"
else
echo -e "$_b ROOT ($runfrom) FREE SPACE IS:\t\t"$_g"$rootfree""$_x"
fi
[ "$compress" = "true" ] && compress || dobackup

View File

@@ -0,0 +1 @@
armbian-install

View File

@@ -0,0 +1,3 @@
if which plymouth >/dev/null 2>&1; then
FRAMEBUFFER=y
fi