Files
build/packages/bsp/common/usr/sbin/nand-sata-install
Gauthier Provost 59af84c07c Helios4: Add SPI bootloader install feature (#1126)
* Helios4: Add workaround for SPI and SATA concurrent access issue

Concurrent access on SPI NOR and SATA drives can lead to unstable SATA.
Therefore as workaround, disable SATA controller when SPI flash access
is needed and make it as user configurable item in armbianEnv.txt

This workaround might applies to Clearfog too.

Signed-off-by: Aditya Prayoga <aditya@kobol.io>

* Helios4: Add U-Boot SPI

Signed-off-by: Aditya Prayoga <aditya@kobol.io>

* Helios4: Add SPI bootloader install feature

This will allow to use nand-sata-install to perform the following operations on Helios4 :
- Install bootloader to SPI NOR Flash (Option 5 in Menu).
- Copy RootFS to USB storage in order to boot from SPI with RootFS on USB (Option 6 in Menu).

* Unmount temp mount points in create_armbian() instead of hardcoded /dev/sda
2018-10-08 13:44:36 +02:00

664 lines
26 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) Authors: http://www.armbian.com/authors
#
# Tool to transfer the rootfs of an already running Armbian installation from SD card
# to NAND, eMMC, SATA 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.
# Import:
# DIR: path to u-boot directory
# write_uboot_platform: function to write u-boot to a block device
[[ -f /usr/lib/u-boot/platform_install.sh ]] && source /usr/lib/u-boot/platform_install.sh
# script configuration
CWD="/usr/lib/nand-sata-install"
EX_LIST="${CWD}/exclude.txt"
[ -f /etc/default/openmediavault ] && echo '/srv/*' >>"${EX_LIST}"
nanddevice="/dev/nand"
logfile="/var/log/nand-sata-install.log"
# read in board info
[[ -f /etc/armbian-release ]] && source /etc/armbian-release
backtitle="Armbian for $BOARD_NAME install script, http://www.armbian.com"
title="NAND, eMMC, SATA, USB and NVMe 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"
case ${LINUXFAMILY} in
rk3328|rk3399|rockchip64)
FIRSTSECTOR=32768
;;
*)
FIRSTSECTOR=8192
;;
esac
#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_device="${root_partition::-2}"
# find targets: NAND, EMMC, SATA, SPI flash, NVMe
[[ -b /dev/nand ]] && nandcheck=$(ls -d -1 /dev/nand* | grep -w 'nand' | awk '{print $NF}');
emmccheck=$(ls -d -1 /dev/mmcblk* | grep -w 'mmcblk[0-9]' | grep -v "$root_partition_device");
diskcheck=$(lsblk -l | awk -F" " '/ disk / {print $1}' | egrep '^sd|^nvme')
spicheck=$(grep 'mtd' /proc/partitions | awk '{print $NF}')
# define makefs and mount options
declare -A mkopts mountopts
# for ARMv7 remove 64bit feature from default mke2fs format features
if [[ $LINUXFAMILY == mvebu ]]; then
mkopts[ext2]='-O ^64bit -qF'
mkopts[ext3]='-O ^64bit -qF'
mkopts[ext4]='-O ^64bit -qF'
else
mkopts[ext2]='-qF'
mkopts[ext3]='-qF'
mkopts[ext4]='-qF'
fi
mkopts[btrfs]='-f'
mkopts[f2fs]=''
mountopts[ext2]='defaults,noatime,nodiratime,commit=600,errors=remount-ro,x-gvfs-hide 0 1'
mountopts[ext3]='defaults,noatime,nodiratime,commit=600,errors=remount-ro,x-gvfs-hide 0 1'
mountopts[ext4]='defaults,noatime,nodiratime,commit=600,errors=remount-ro,x-gvfs-hide 0 1'
mountopts[btrfs]='defaults,noatime,nodiratime,commit=600,compress=lzo,x-gvfs-hide 0 2'
mountopts[f2fs]='defaults,noatime,nodiratime,x-gvfs-hide 0 2'
# Create boot and root file system $1 = boot, $2 = root (Example: create_armbian "/dev/nand1" "/dev/sda3")
create_armbian()
{
# create mount points, mount and clean
TempDir=$(mktemp -d /mnt/${0##*/}.XXXXXX || exit 1)
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 || mount $2 ${TempDir}/rootfs )
else
[[ -n $2 ]] && ( mount -o compress-force=zlib $2 ${TempDir}/rootfs || mount $2 ${TempDir}/rootfs )
[[ -n $1 && $1 != "spi" ]] && mount $1 ${TempDir}/bootfs
fi
rm -rf ${TempDir}/bootfs/* ${TempDir}/rootfs/*
# sata root part
# UUID=xxx...
satauuid=$(blkid -o export $2 | grep -w UUID)
# SD card boot part -- wrong since more than one entry on various platforms
# UUID=xxx...
sduuid=$(blkid -o export /dev/mmcblk*p1 | grep -w UUID | grep -v "$root_partition_device")
# 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
umountdevice "$1"; umountdevice "$2"
exit 1
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 | egrep -v "log2ram|folder2ram" | sort >> $logfile
# stop running services
echo -e "\nFiles currently open for writing:" >> $logfile
lsof / | awk 'NR==1 || $4~/[0-9][uw]/' | grep -v "^COMMAND" >> $logfile
echo -e "\nTrying to stop running services to minimize open files:\c" >> $logfile
StopRunningServices "nfs-|smbd|nmbd|winbind|ftpd|netatalk|monit|cron|webmin|rrdcached" >> $logfile
StopRunningServices "fail2ban|log2ram|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 / | 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
rsync -avrltD --delete --exclude-from=$EX_LIST / ${TempDir}/rootfs | nl | awk '{ printf "%.0f\n", 100*$1/"'"$TODO"'" }' \
| dialog --backtitle "$backtitle" --title " $title " --gauge "\n\n Transferring rootfs to $2 ($USAGE MB). \n\n \
This will take approximately $(( $((USAGE/300)) * 5 )) 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 40
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,nodiratime,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
umountdevice "/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* ]]; 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
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
else
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
mkimage -C none -A arm -T script -d ${TempDir}/bootfs/boot/boot.cmd ${TempDir}/bootfs/boot/boot.scr >/dev/null 2>&1 || (echo "Error"; exit 0)
# 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 [[ $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
sed -e 's,rootfstype=.*,rootfstype='$eMMCFilesystemChoosen',g' -i ${TempDir}/bootfs/boot/armbianEnv.txt
else
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 -1
fi
write_uboot_platform $DIR $emmccheck
fi
# Boot from SD card, root = SATA / USB
#
if [[ $2 == ${DISK_ROOT_PART} && -z $1 ]]; 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
[[ -f /boot/boot.cmd ]] && mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr >/dev/null 2>&1 || (echo "Error"; exit 0)
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
# Boot from SPI, root = SATA / USB
#
if [[ $1 == *spi* ]]; then
sed -e 's,rootdev=.*,rootdev='"$satauuid"',g' -i ${TempDir}/rootfs/boot/armbianEnv.txt
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
[[ $1 != "spi" ]] && unmount ${TempDir}/bootfs
} # create_armbian
# Accept device as parameter: for example /dev/sda unmounts all their mounts
umountdevice()
{
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
} # umountdevice
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.
#
formatnand()
{
[[ ! -e /dev/nand ]] && echo "NAND error" && exit 0
show_nand_warning
dialog --title "$title" --backtitle "$backtitle" --infobox "\nFormating ... up to one minute." 5 40
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
#
formatemmc()
{
# choose and create fs
IFS=" "
BTRFS=$(grep -o btrfs /proc/filesystems)
FilesystemTargets="1 ext4 2 ext3 3 ext2 4 f2fs"
[[ -n $BTRFS && `uname -r | grep '^4.' ` ]] && FilesystemTargets=$FilesystemTargets" 5 $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 1
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 ))}")
if [[ $CAPACITY -lt 4000000 ]]; then
# Leave 2 percent unpartitioned when eMMC size is less than 4GB (unlikely)
LASTSECTOR=$(( 32 * $(parted ${1} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 98 / 3200))}") -1 ))
else
# Leave 1 percent unpartitioned
LASTSECTOR=$(( 32 * $(parted ${1} unit s print -sm | awk -F":" "/^${QUOTED_DEVICE}/ {printf (\"%0d\", ( \$2 * 99 / 3200))}") -1 ))
fi
parted -s $1 -- mklabel msdos
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
# 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} + 131071 ))s
parted -s $1 -- mkpart primary $partedFsType $(( ${FIRSTSECTOR} + 131072 ))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} + 131071 ))s
parted -s $1 -- mkpart primary $partedFsType $(( ${FIRSTSECTOR} + 131072 ))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
#
formatdisk()
{
# 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 2 ext3 3 ext2"
[[ -n $BTRFS && `uname -r | grep '^4.' ` && $choice != 6 ]] && FilesystemTargets=$FilesystemTargets" 4 $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 1
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.
checkpartitions()
{
IFS=" "
AvailablePartitions=$(lsblk -l | awk -F" " '/ part / {print $1}' | egrep '^sd|^nvme')
if [[ -z $AvailablePartitions ]]; then
dialog --title "$title" --backtitle "$backtitle" --colors --msgbox \
"\n\Z1There are no avaliable partitions. Please create them.\Zn" 7 60
# We need gdisk for proper partition alignment
apt-get -y -q install gdisk >/dev/null 2>&1
gdisk /dev/$diskcheck
fi
AvailablePartitions=$(lsblk -l | awk -F" " '/ part / {print $1}' | egrep '^sd|^nvme' | sed 's|^|/dev/|' | nl | xargs echo -n)
PartitionOptions=($AvailablePartitions)
PartitionCmd=(dialog --title "Select destination:" --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
PartitionChoices=$("${PartitionCmd[@]}" "${PartitionOptions[@]}" 2>&1 >/dev/tty)
[[ $? -ne 0 ]] && exit 1
DISK_ROOT_PART=${PartitionOptions[(2*$PartitionChoices)-1]}
}
# choose target NVMe partition.
checknvmetarget()
{
IFS=" "
NVMeTargets=$(awk '/nvme0n1p/ {print "/dev/"$4}' </proc/partitions | nl | xargs echo -n)
if [[ -z $NVMeTargets ]]; then
dialog --title "$title" --backtitle "$backtitle" --colors --msgbox \
"\n\Z1There are no avaliable partitions. Please create them.\Zn" 7 60
# We need gdisk for proper partition alignment
apt-get -y -q install gdisk >/dev/null 2>&1
gdisk /dev/$nvmecheck
fi
NVMeTargets=$(awk '/nvme0n1p/ {print "/dev/"$4}' </proc/partitions | nl | xargs echo -n)
NVMeOptions=($NVMeTargets)
NVMeCmd=(dialog --title "Select destination:" --backtitle "$backtitle" --menu "\n$infos" 10 60 16)
NVMeChoices=$("${NVMeCmd[@]}" "${NVMeOptions[@]}" 2>&1 >/dev/tty)
[[ $? -ne 0 ]] && exit 1
DISK_ROOT_PART=${NVMeOptions[(2*$NVMeChoices)-1]}
}
# show warning [TEXT]
ShowWarning()
{
dialog --title "$title" --backtitle "$backtitle" --cr-wrap --colors --yesno " \Z1$(toilet -f mono12 WARNING)\Zn\n$1" 17 74
[[ $? -ne 0 ]] && exit 1
}
# try to stop running services
StopRunningServices()
{
systemctl --state=running | awk -F" " '/.service/ {print $1}' | sort -r | \
egrep -e "$1" | while read ; do
echo -e "\nStopping ${REPLY} \c"
systemctl stop ${REPLY} 2>&1
done
}
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 1
fi
# Check if we run it from SD card
# TODO: Disable/remove this in the future
case ${root_partition_device} in
/dev/mmcblk*) # mmc device, we can continue
:
;;
*)
dialog --title "$title" --backtitle "$backtitle" --colors --infobox "\n\Z1This tool must run from SD-card! \Zn" 5 37
exit 1
;;
esac
[ -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="NAND"
dest_boot="/dev/nand1"
dest_root="/dev/nand2"
fi
[[ -n $nandcheck || -n $emmccheck ]] && options+=(1 "Boot from $ichip - system on $ichip")
[[ ( -n $nandcheck || -n $emmccheck ) && -n $diskcheck ]] && options+=(2 "Boot from $ichip - system on SATA, USB or NVMe")
[[ -n $diskcheck ]] && options+=(3 "Boot from SD - system on SATA, USB or NVMe")
[[ ( $LINUXFAMILY == odroidxu4 || $LINUXFAMILY == mvebu* ) && ( -b /dev/mmcblk0boot0 || -b /dev/mmcblk1boot0 ) ]] && options+=(4 "Update the bootloader on a special eMMC partition")
[[ -n $spicheck && $(type -t write_uboot_platform_mtd) == function ]] && options+=(5 "Install the bootloader to SPI Flash")
[[ -n $spicheck ]] && options+=(6 "Boot from SPI - system on SATA, USB or NVMe")
[[ ${#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 1
for choice in $choices
do
case $choice in
1)
title="$ichip install"
command="Power off"
ShowWarning "This script will erase your $ichip. Continue?"
if [[ -n $emmccheck ]]; then
umountdevice "$emmccheck"
formatemmc "$emmccheck"
else
umountdevice "/dev/nand"
formatnand
fi
create_armbian "$dest_boot" "$dest_root"
;;
2)
title="$ichip boot | USB/SATA/NVMe root install"
command="Power off"
checkpartitions
ShowWarning "This script will erase your $ichip and $DISK_ROOT_PART. Continue?"
if [[ -n $emmccheck ]]; then
umountdevice "$emmccheck"
formatemmc "$emmccheck"
else
umountdevice "/dev/nand"
formatnand
fi
umountdevice "${DISK_ROOT_PART//[0-9]*/}"
formatdisk "$DISK_ROOT_PART"
create_armbian "$dest_boot" "$DISK_ROOT_PART"
;;
3)
title="MMC (SD/eMMC) boot | USB/SATA/NVMe root install"
command="Reboot"
checkpartitions
ShowWarning "This script will erase your device $DISK_ROOT_PART. Continue?"
formatdisk "$DISK_ROOT_PART"
create_armbian "" "$DISK_ROOT_PART"
;;
4)
if [[ -b /dev/mmcblk0boot0 ]]; then
BOOTPART="/dev/mmcblk0"
elif [[ -b /dev/mmcblk1boot0 ]]; then
BOOTPART="/dev/mmcblk1"
fi
ShowWarning "This script will update the bootloader on $BOOTPART. Continue?"
write_uboot_platform $DIR $BOOTPART
echo "Done"
return
;;
5)
MTD_BLK="/dev/${spicheck}"
ShowWarning "This script will update the bootloader on SPI Flash $MTD_BLK. Continue?"
write_uboot_platform_mtd $DIR $MTD_BLK
echo "Done"
return
;;
6)
# Espressobin has flash boot by default
title="SPI flash boot | USB/SATA/NVMe root install"
command="Power off"
# we need to copy boot
sed -i '/boot/d' $EX_LIST
checkpartitions
ShowWarning "This script will erase your device $DISK_ROOT_PART. Continue?"
formatdisk "$DISK_ROOT_PART"
create_armbian "spi" "$DISK_ROOT_PART"
;;
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 "$@"