mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
* 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
664 lines
26 KiB
Bash
Executable File
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 "$@"
|