This is a workaround for now, we should patch driver to derive MAC address from SID. Also needs firmware included in image to work.
440 lines
16 KiB
Bash
440 lines
16 KiB
Bash
#!/bin/bash
|
|
|
|
### BEGIN INIT INFO
|
|
# Provides: firstrun
|
|
# Required-Start: $all
|
|
# Required-Stop:
|
|
# Should-Start: armhwinfo
|
|
# Default-Start: 2 3 4 5
|
|
# Default-Stop: 0 1 6
|
|
# Short-Description: PLEASE DO NOT INTERRUPT THE FIRST BOOT
|
|
# Description: Something needs to be done when is
|
|
# starting at first time.
|
|
# regenerate ssh host key
|
|
### END INIT INFO
|
|
#
|
|
# Create this file to speed up boot process
|
|
#
|
|
|
|
# Immediately exit if not called by init system
|
|
if [ "X$1" != "Xstart" ]; then
|
|
exit 1
|
|
fi
|
|
|
|
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
Log=/var/log/armhwinfo.log
|
|
|
|
# create helper script to set swap settings
|
|
cat > /tmp/create_swap.sh <<EOT
|
|
#!/bin/bash
|
|
#
|
|
# create swap and adds it into fstab
|
|
#
|
|
# update console info
|
|
setupcon --save
|
|
# 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
|
|
read entropy_after </proc/sys/kernel/random/entropy_avail
|
|
echo -e "### [firstrun] Recreated SSH keys (entropy: \${entropy_before} \${entropy_after})" >>${Log}
|
|
MEMTOTAL=$(( $(awk -F" " '/^MemTotal/ {print $2}' </proc/meminfo) / 1024 ))
|
|
FREESIZE=\$(df -hm / | awk '/\// {print \$(NF-2)}')
|
|
SWAPFILE=/var/swap
|
|
if [[ ! -f "\$SWAPFILE" && "\$FREESIZE" -gt "132" ]]; then
|
|
fallocate -l 128M \$SWAPFILE >/dev/null 2>&1
|
|
if [ $? -eq 1 ]; then dd if=/dev/zero of=\$SWAPFILE bs=1M count=128 status=noxfer >/dev/null 2>&1; fi
|
|
chown root:root \$SWAPFILE
|
|
chmod 0600 \$SWAPFILE
|
|
mkswap \$SWAPFILE >/dev/null 2>&1
|
|
swapon \$SWAPFILE >/dev/null 2>&1
|
|
if ! grep -q swap /etc/fstab; then echo "\$SWAPFILE none swap sw 0 0" >> /etc/fstab; fi
|
|
if ! grep -q swap /etc/sysctl.conf; then echo "vm.swappiness=0" >> /etc/sysctl.conf; fi
|
|
echo -e "\n### [firstrun] Created 128MB emergency swap as \$SWAPFILE" >>${Log}
|
|
fi
|
|
# RAMLOG
|
|
if [[ "$(apt-cache policy ramlog | grep Installed)" != "" ]]; then
|
|
service ramlog enable
|
|
# if we have 1G ram reduce RAMLOG size
|
|
if [[ "\$MEMTOTAL" -lt "1100" ]]; then
|
|
if [ -f "/etc/default/ramlog" ]; then
|
|
sed -e 's/TMPFS_RAMFS_SIZE=512m/TMPFS_RAMFS_SIZE=256m/g' -i /etc/default/ramlog
|
|
fi
|
|
elif [[ "\$MEMTOTAL" -lt "600" ]]; then
|
|
if [ -f "/etc/default/ramlog" ]; then
|
|
sed -e 's/TMPFS_RAMFS_SIZE=512m/TMPFS_RAMFS_SIZE=192m/g' -i /etc/default/ramlog
|
|
fi
|
|
fi
|
|
fi
|
|
while [ -f /tmp/firstrun_running ]; do sleep 1; done
|
|
if [ -f "/var/run/reboot" ]; then
|
|
wall -n "Performing automatic reboot in 5 seconds"
|
|
sleep 5
|
|
reboot
|
|
fi
|
|
rm -f /tmp/create_swap.sh
|
|
sync &
|
|
EOT
|
|
chmod +x /tmp/create_swap.sh
|
|
|
|
collect_information() {
|
|
# get some info about the board
|
|
source /etc/armbian-release
|
|
DISTRIBUTION=$(lsb_release -cs)
|
|
|
|
# enable BT on cubietruck
|
|
[[ "$BOARD" == "cubietruck" ]] && update-rc.d brcm40183-patch defaults
|
|
|
|
# enable BT on Banana M2+
|
|
[[ "$BOARD" == "bananapim2plus" || "$BOARD" == "nanopiair" ]] && update-rc.d ap6212-bluetooth defaults
|
|
|
|
# enable BT on Solidrun boards
|
|
[[ "$BOARD" == "Cubox i2eX/i4" ]] && update-rc.d brcm4330-patch defaults && /etc/init.d/brcm4330-patch start
|
|
|
|
case ${DISTRIBUTION} in
|
|
wheezy)
|
|
root_device=$(mountpoint -d /)
|
|
for file in /dev/* ; do
|
|
CURRENT_DEVICE=$(printf "%d:%d" $(stat --printf="0x%t 0x%T" $file))
|
|
if [ $CURRENT_DEVICE = $root_device ]; then
|
|
root_partition=$file
|
|
break;
|
|
fi
|
|
done
|
|
rootfstype=$(blkid -s TYPE -o value $root_partition)
|
|
;;
|
|
*)
|
|
ROOTFS=$(findmnt / | awk -F" " '/\/dev\// {print $2"\t"$3}')
|
|
set ${ROOTFS}
|
|
root_partition=$1
|
|
rootfstype=$2
|
|
;;
|
|
esac
|
|
} # collect_information
|
|
|
|
adjust_sunxi_settings() {
|
|
# set some mac address for BT
|
|
[[ "$(lsmod | grep dhd)" != "" ]] && \
|
|
(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})
|
|
|
|
# set current OPi Zero WiFi address permanently
|
|
[[ "$(lsmod | grep xradio_wlan)" != "" ]] && \
|
|
(MACADDR=$(ifconfig wlan0 | awk -F" " '/^wlan0/ {print $5}' | tr '[:lower:]' '[:upper:]') ; \
|
|
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})
|
|
|
|
# change serial port for BT on NanoPi Air
|
|
# relink /etc/network/interfaces on OPi Lite and NanoPi Air
|
|
case ${BOARD_NAME} in
|
|
"NanoPi Air"|"Orange Pi Lite")
|
|
sed -i "s/^PORT=.*/PORT=ttyS3/" /etc/default/ap6212
|
|
cd /etc/network/ && ln -sf interfaces.network-manager interfaces
|
|
;;
|
|
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
|
|
} # adjust_sunxi_settings
|
|
|
|
do_expand_rootfs() {
|
|
# get device node for boot media
|
|
DEVICE="/dev/"$(lsblk -idn -o NAME | grep -w mmcblk0)
|
|
if [ "${DEVICE}" = "/dev/" ]; then return ; fi
|
|
QUOTED_DEVICE=$(echo "${DEVICE}" | sed 's:/:\\\/:g')
|
|
|
|
# get count of partitions and their boundaries
|
|
PARTITIONS=$(( $(grep -c ${DEVICE##*/}p /proc/partitions) ))
|
|
PARTSTART=$(parted ${DEVICE} unit s print -sm | tail -1 | cut -d: -f2 | sed 's/s//') # start of first partition
|
|
PARTEND=$(parted ${DEVICE} unit s print -sm | head -3 | tail -1 | cut -d: -f3 | sed 's/s//') # end of first partition
|
|
STARTFROM=$(( ${PARTEND} + 1 ))
|
|
[[ ${PARTITIONS} == 1 ]] && STARTFROM=${PARTSTART}
|
|
|
|
# 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"
|
|
ResizeLog="Resize rule ${RESIZE_VALUE} defined for ${root_partition}"
|
|
case ${RESIZE_VALUE} in
|
|
*%)
|
|
# percentage value, we try to use 16MiB to align partitions since this is
|
|
# the erase block size of more recent SD cards (512 byte sectors, so we use 32
|
|
# as divider and substract 1)
|
|
PERCENTAGE=$(echo ${RESIZE_VALUE} | tr -c -d '[:digit:]')
|
|
LASTSECTOR=$(( 32 * $(parted ${DEVICE} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * ${PERCENTAGE} / 3200))}") -1 ))
|
|
if [ ${LASTSECTOR} -lt ${PARTEND} ]; then unset LASTSECTOR ; fi
|
|
;;
|
|
*s)
|
|
# sector value, we use it directly
|
|
LASTSECTOR=$(echo ${RESIZE_VALUE} | tr -c -d '[:digit:]')
|
|
if [ ${LASTSECTOR} -lt ${PARTEND} ]; then unset LASTSECTOR ; fi
|
|
;;
|
|
esac
|
|
else
|
|
# Unattended mode. We run a q&d benchmark to be able to identify cards way too slow easily
|
|
cd /root
|
|
echo -e "\n### quick iozone test:$(iozone -e -I -a -s 1M -r 4k -i 0 -i 1 -i 2 | grep '^ 1024' | sed 's/ 1024 //')" >>/var/log/armhwinfo.log
|
|
|
|
# check device capacity. If 4GB 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)
|
|
CAPACITY=$(parted ${DEVICE} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", \$2 / ( 1024 / \$4 ))}")
|
|
if [ ${CAPACITY} -lt 4000000 ]; then
|
|
SPAREAREA=$(( ${CAPACITY} / 20000 ))
|
|
LASTSECTOR=$(parted ${DEVICE} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {print \$2 - (${SPAREAREA} * 1024 * ( 1024 / \$4 ))}")
|
|
if [ ${LASTSECTOR} -lt ${PARTEND} ]; then
|
|
unset LASTSECTOR
|
|
else
|
|
ResizeLog="4GB media so leaving 200MB spare area on ${root_partition}"
|
|
fi
|
|
elif [ ${CAPACITY} -lt 8000000 ]; then
|
|
# Leave 2 percent unpartitioned
|
|
LASTSECTOR=$(( 32 * $(parted ${DEVICE} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 98 / 3200))}") -1 ))
|
|
if [ ${LASTSECTOR} -lt ${PARTEND} ]; then
|
|
unset LASTSECTOR
|
|
else
|
|
ResizeLog="8GB media so leaving 2 percent spare area on ${root_partition}"
|
|
fi
|
|
else
|
|
# Leave 1 percent unpartitioned
|
|
LASTSECTOR=$(( 32 * $(parted ${DEVICE} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 99 / 3200))}") -1 ))
|
|
if [ ${LASTSECTOR} -lt ${PARTEND} ]; then
|
|
unset LASTSECTOR
|
|
else
|
|
ResizeLog="Leaving 1 percent spare area on ${root_partition}"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Start resizing
|
|
echo -e "\n### [firstrun] ${ResizeLog}. Start resizing Partition now:\n" >>${Log}
|
|
cat /proc/partitions >>${Log}
|
|
echo -e "\nExecuting fdisk, fsck and partprobe:" >>${Log}
|
|
UtilLinuxVersion=$(echo q | fdisk ${DEVICE} | awk -F"util-linux " '/ fdisk / {print $2}')
|
|
if [ "X${PARTITIONS}" = "X1" ]; then
|
|
case ${UtilLinuxVersion} in
|
|
2.27.1*)
|
|
# if dealing with fdisk from util-linux 2.27.1 we need a workaround for just 1 partition
|
|
# https://github.com/igorpecovnik/lib/issues/353#issuecomment-224728506
|
|
((echo d; echo n; echo p; echo ; echo $STARTFROM; echo ${LASTSECTOR} ; echo w;) | fdisk ${DEVICE}) >>${Log} 2>&1 || true
|
|
;;
|
|
*)
|
|
((echo d; echo $PARTITIONS; echo n; echo p; echo ; echo $STARTFROM; echo ${LASTSECTOR} ; echo w;) | fdisk ${DEVICE}) >>${Log} 2>&1 || true
|
|
;;
|
|
esac
|
|
else
|
|
((echo d; echo $PARTITIONS; echo n; echo p; echo ; echo $STARTFROM; echo ${LASTSECTOR} ; echo w;) | fdisk ${DEVICE}) >>${Log} 2>&1 || true
|
|
fi
|
|
s=0
|
|
fsck -f $root_partition >>${Log} 2>&1 || true
|
|
partprobe ${DEVICE} >>${Log} 2>&1 || s=$?
|
|
echo -e "\nNew partition table:\n" >>${Log}
|
|
cat /proc/partitions >>${Log}
|
|
echo -e "\nNow executing resize2fs to enlarge ${root_partition} to the maximum:\n" >>${Log}
|
|
resize2fs $root_partition >>${Log} 2>&1 || true
|
|
|
|
# force reboot if first run is issued on eMMC (bug on C2)
|
|
[[ $(find /sys -name oemid | grep emmc) ]] && s=1
|
|
|
|
# check whether reboot is necessary for resize2fs to take effect
|
|
FREESIZE=$(df -hm / | awk '/\// {print $(NF-2)}')
|
|
if [[ "$DISTRIBUTION" == "wheezy" || "$s" != "0" || "$FREESIZE" -lt "152" ]]; then
|
|
touch /var/run/reboot
|
|
update-rc.d resize2fs defaults >/dev/null 2>&1
|
|
echo -e "\n### [firstrun] Automated reboot needed to let /etc/init.d/resize2fs do the job" >>${Log}
|
|
fi
|
|
return 0
|
|
} # do_expand_rootfs
|
|
|
|
check_prerequisits() {
|
|
for needed_tool in fdisk parted partprobe resize2fs ; do
|
|
which ${needed_tool} >/dev/null 2>&1 || exit 1
|
|
done
|
|
} # check_prerequisits
|
|
|
|
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 config/armbian_first_run.txt
|
|
|
|
#-----------------------------------------------------------------------------
|
|
#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"
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# - 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"
|
|
fi
|
|
|
|
#-----------------------------------------------------------------------------
|
|
# Set Network
|
|
if [[ $FR_net_change_defaults == 1 ]]; then
|
|
# - Get 1st index of available wlan and eth adapters
|
|
local fp_ifconfig_tmp='/tmp/.ifconfig'
|
|
ifconfig -a > "$fp_ifconfig_tmp" #export to file, should be quicker in loop than calling ifconfig each time.
|
|
|
|
# find eth[0-9]
|
|
for ((i=0; i<=9; i++))
|
|
do
|
|
if (( $(cat "$fp_ifconfig_tmp" | grep -ci -m1 "eth$i") )); then
|
|
eth_index=$i
|
|
break
|
|
fi
|
|
done
|
|
|
|
# find wlan[0-9]
|
|
for ((i=0; i<=9; i++))
|
|
do
|
|
if (( $(cat "$fp_ifconfig_tmp" | grep -ci -m1 "wlan$i") )); then
|
|
wlan_index=$i
|
|
break
|
|
fi
|
|
done
|
|
|
|
rm "$fp_ifconfig_tmp"
|
|
|
|
# - Kill dhclient
|
|
killall -w dhclient
|
|
|
|
# - Drop Connections
|
|
ifdown eth$eth_index --force
|
|
ifdown wlan$wlan_index --force
|
|
|
|
# - Wifi enable
|
|
if [[ $FR_net_wifi_enabled == 1 ]]; then
|
|
|
|
#Enable Wlan, disable Eth
|
|
FR_net_ethernet_enabled=0
|
|
sed -i "/allow-hotplug wlan$wlan_index/c\allow-hotplug wlan$wlan_index" /etc/network/interfaces
|
|
sed -i "/allow-hotplug eth$eth_index/c\#allow-hotplug eth$eth_index" /etc/network/interfaces
|
|
|
|
#Set SSid (covers both WEP and WPA)
|
|
sed -i "/wireless-essid /c\ wireless-essid $FR_net_wifi_ssid" /etc/network/interfaces
|
|
sed -i "/wpa-ssid /c\ wpa-ssid $FR_net_wifi_ssid" /etc/network/interfaces
|
|
|
|
#Set Key (covers both WEP and WPA)
|
|
sed -i "/wireless-key /c\ wireless-key $FR_net_wifi_key" /etc/network/interfaces
|
|
sed -i "/wpa-psk /c\ wpa-psk $FR_net_wifi_key" /etc/network/interfaces
|
|
|
|
#Set wifi country code
|
|
iw reg set "$FR_net_wifi_countrycode"
|
|
|
|
#Disable powersaving for known chips that suffer from powersaving features causing connection dropouts.
|
|
# This is espically true for the 8192cu and 8188eu.
|
|
#FOURDEE: This may be better located as default in ARMbian during build (eg: common), as currently, not active until after a reboot.
|
|
# - Realtek | all use the same option, so create array.
|
|
local realtek_array=(
|
|
"8192cu"
|
|
"8188eu"
|
|
)
|
|
|
|
for ((i=0; i<${#realtek_array[@]}; i++))
|
|
do
|
|
echo -e "options ${realtek_array[$i]} rtw_power_mgnt=0" > /etc/modprobe.d/realtek_"${realtek_array[$i]}".conf
|
|
done
|
|
|
|
unset realtek_array
|
|
|
|
# - Ethernet enable
|
|
elif [[ $FR_net_ethernet_enabled == 1 ]]; then
|
|
|
|
#Enable Eth, disable Wlan
|
|
FR_net_wifi_enabled=0
|
|
sed -i "/allow-hotplug eth$eth_index/c\allow-hotplug eth$eth_index" /etc/network/interfaces
|
|
#sed -i "/allow-hotplug wlan$wlan_index/c\#allow-hotplug wlan$wlan_index" /etc/network/interfaces
|
|
|
|
fi
|
|
|
|
# - Static IP enable
|
|
if [[ $FR_net_use_static == 1 ]]; then
|
|
if [[ $FR_net_wifi_enabled == 1 ]]; then
|
|
sed -i "/iface wlan$wlan_index inet/c\iface wlan$wlan_index inet static" /etc/network/interfaces
|
|
elif [[ $FR_net_ethernet_enabled == 1 ]]; then
|
|
sed -i "/iface eth$eth_index inet/c\iface eth$eth_index inet static" /etc/network/interfaces
|
|
fi
|
|
|
|
#This will change both eth and wlan entries, however, as only 1 adapater is enabled by this feature, should be fine.
|
|
sed -i "/^#address/c\address $FR_net_static_ip" /etc/network/interfaces
|
|
sed -i "/^#netmask/c\netmask $FR_net_static_mask" /etc/network/interfaces
|
|
sed -i "/^#gateway/c\gateway $FR_net_static_gateway" /etc/network/interfaces
|
|
sed -i "/^#dns-nameservers/c\dns-nameservers $FR_net_static_dns" /etc/network/interfaces
|
|
fi
|
|
|
|
# - Restart Networking
|
|
if [[ "$DISTRIBUTION" == "wheezy" || "$DISTRIBUTION" == "trusty" ]]; then
|
|
service networking restart
|
|
else
|
|
systemctl daemon-reload
|
|
systemctl restart networking
|
|
fi
|
|
|
|
# - Manually bring up adapters (just incase)
|
|
if [[ $FR_net_wifi_enabled == 1 ]]; then
|
|
ifup wlan$wlan_index
|
|
elif [[ $FR_net_ethernet_enabled == 1 ]]; then
|
|
ifup eth$eth_index
|
|
fi
|
|
fi
|
|
fi
|
|
} #do_firstrun_automated_user_configuration
|
|
|
|
main() {
|
|
touch /tmp/firstrun_running
|
|
|
|
check_prerequisits
|
|
collect_information
|
|
|
|
if [[ "$rootfstype" == "ext4" && ! -f "/root/.no_rootfs_resize" ]]; then
|
|
do_expand_rootfs
|
|
fi
|
|
|
|
do_firstrun_automated_user_configuration &
|
|
|
|
/tmp/create_swap.sh &
|
|
|
|
# old distros can't handle allow-hotplug
|
|
if [[ "$DISTRIBUTION" == "wheezy" || "$DISTRIBUTION" == "trusty" ]]; then
|
|
sed -i "s/allow-hotplug eth/auto eth/" /etc/network/interfaces
|
|
sed -i "s/allow-hotplug wlan/auto wlan/" /etc/network/interfaces
|
|
fi
|
|
|
|
# some hardware workarounds
|
|
case ${LINUXFAMILY} in
|
|
sun7i|sun8i)
|
|
adjust_sunxi_settings
|
|
;;
|
|
pine64)
|
|
if [ -z "$(grep ethaddr /boot/uEnv.txt)" ] && [ -f "/sys/class/net/eth0/address" ]; then
|
|
echo "ethaddr=$(cat /sys/class/net/eth0/address)" >> /boot/uEnv.txt
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
update-rc.d -f firstrun remove >/dev/null 2>&1
|
|
rm /tmp/firstrun_running
|
|
} # main
|
|
|
|
main
|