--- /dev/null
+#!/bin/bash
+
+declare FORMAT=""
+declare DEVICE=""
+
+# Binaires array for fusing
+declare -a FUSING_BINARY_ARRAY
+declare -i FUSING_BINARY_NUM=0
+
+declare CONV_ASCII=""
+declare -i FUS_ENTRY_NUM=0
+
+# binary name | part number | bs
+declare -a PART_TABLE=(
+ "boot.img" 1 4M
+ "rootfs.img" 2 4M
+ "system-data.img" 3 4M
+ "user.img" 5 4M
+ "modules.img" 6 4M
+ "ramdisk.img" 7 4M
+ "ramdisk-recovery.img" 8 4M
+ )
+
+declare -r -i PART_TABLE_ROW=3
+declare -r -i PART_TABLE_COL=${#PART_TABLE[*]}/${PART_TABLE_ROW}
+
+# partition table support
+function get_index_use_name () {
+ local -r binary_name=$1
+
+ for ((idx=0;idx<$PART_TABLE_COL;idx++)); do
+ if [ ${PART_TABLE[idx * ${PART_TABLE_ROW} + 0]} == $binary_name ]; then
+ return $idx
+ fi
+ done
+
+ # return out of bound index
+ return $idx
+}
+
+function print_message () {
+ local color=$1
+ local message=$2
+
+ tput setaf $color
+ tput bold
+ echo ""
+ echo $message
+ tput sgr 0
+}
+
+function check_ddversion () {
+ # NOTE
+ # before coreutils dd 8.24, dd doesn't support "status=progress"
+ # and the option causes fusing failure. For backward compatibility,
+ # do not use the option for old dd
+ local version=`dd --version | head -1 | awk '{print $3}'`
+ local major=${version%%.*}
+ local version=${version:`expr index $version .`}
+ local minor=${version%%.*}
+
+ if [ $major -lt 8 ]; then
+ OLD_DD=1
+ elif [ $major -eq 8 -a $minor -lt 24 ]; then
+ OLD_DD=1
+ fi
+}
+
+function fusing_image () {
+ local -r fusing_img=$1
+
+ # get binary info using basename
+ get_index_use_name $(basename $fusing_img)
+ local -r -i part_idx=$?
+
+ if [ $part_idx -ne $PART_TABLE_COL ];then
+ local -r device=$DEVICE${PART_TABLE[${part_idx} * ${PART_TABLE_ROW} + 1]}
+ local -r bs=${PART_TABLE[${part_idx} * ${PART_TABLE_ROW} + 2]}
+ else
+ echo "Not supported binary: $fusing_img"
+ return
+ fi
+
+ local -r input_size=`du -b $fusing_img | awk '{print $1}'`
+ local -r input_size_mb=`expr $input_size / 1024 / 1024`
+
+ print_message 2 "[Fusing $1 ($input_size_mb MiB)]"
+ umount $device
+ if [ $OLD_DD == 1 ]; then
+ dd if=$fusing_img | pv -s $input_size | dd of=$device bs=$bs
+ else
+ dd if=$fusing_img of=$device bs=$bs status=progress oflag=direct
+ fi
+
+ local -r fstype=`blkid -o value -s TYPE $device`
+ if [[ "$fstype" =~ "ext" ]]; then
+ resize2fs -f $device
+ fi
+}
+
+function fuse_image_tarball () {
+ local -r filepath=$1
+ local -r temp_dir="tar_tmp"
+
+ mkdir -p $temp_dir
+ tar xvf $filepath -C $temp_dir
+ cd $temp_dir
+
+ for file in *
+ do
+ fusing_image $file
+ done
+
+ cd ..
+ rm -rf $temp_dir
+ eval sync
+}
+
+function fuse_image () {
+
+ if [ "$FUSING_BINARY_NUM" == 0 ]; then
+ return
+ fi
+
+ for ((fuse_idx = 0 ; fuse_idx < $FUSING_BINARY_NUM ; fuse_idx++))
+ do
+ local filename=${FUSING_BINARY_ARRAY[fuse_idx]}
+
+ case "$filename" in
+ *.tar | *.tar.gz)
+ fuse_image_tarball $filename
+ ;;
+ *)
+ fusing_image $filename
+ ;;
+ esac
+ done
+ echo ""
+}
+
+# partition format
+function mkpart_3 () {
+ # NOTE: if your sfdisk version is less than 2.26.0, then you should use following sfdisk command:
+ # sfdisk --in-order --Linux --unit M $DISK <<-__EOF__
+
+ # NOTE: sfdisk 2.26 doesn't support units other than sectors and marks --unit option as deprecated.
+ # The input data needs to contain multipliers (MiB) instead.
+ local version=`sfdisk -v | awk '{print $4}'`
+ local major=${version%%.*}
+ local version=${version:`expr index $version .`}
+ local minor=${version%%.*}
+ local sfdisk_new=0
+
+ if [ $major -gt 2 ]; then
+ sfdisk_new=1
+ else
+ if [ $major -eq 2 -a $minor -ge 26 ]; then
+ sfdisk_new=1
+ fi
+ fi
+
+ local -r DISK=$DEVICE
+ local -r SIZE=`sfdisk -s $DISK`
+ local -r SIZE_MB=$((SIZE >> 10))
+
+ local -r BOOT_SZ=128
+ local -r ROOTFS_SZ=3072
+ local -r DATA_SZ=512
+ local -r MODULE_SZ=100
+ local -r RAMDISK_SZ=8
+ local -r RAMDISK_RECOVERY_SZ=32
+ local -r RESERVED0_SZ=8
+ local -r RESERVED1_SZ=64
+ local -r RESERVED2_SZ=128
+ if [ $sfdisk_new == 1 ]; then
+ local -r EXTEND_SZ=8
+ else
+ local -r EXTEND_SZ=10
+ fi
+
+ let "USER_SZ = $SIZE_MB - $BOOT_SZ - $ROOTFS_SZ - $DATA_SZ - $MODULE_SZ - $RAMDISK_SZ - $EXTEND_SZ"
+ let "USER_SZ = $SIZE_MB - $BOOT_SZ - $ROOTFS_SZ - $DATA_SZ - $MODULE_SZ - $RAMDISK_SZ - $RAMDISK_RECOVERY_SZ - $RESERVED0_SZ - $EXTEND_SZ - $RESERVED1_SZ - $RESERVED2_SZ"
+
+ local -r BOOT=boot
+ local -r ROOTFS=rootfs
+ local -r SYSTEMDATA=system-data
+ local -r USER=user
+ local -r MODULE=modules
+ local -r RAMDISK=ramdisk
+ local -r RAMDISK_RECOVERY=ramdisk-recovery
+ local -r RESERVED0=reserved0
+ local -r RESERVED1=reserved1
+ local -r RESERVED2=reserved2
+
+ if [[ $USER_SZ -le 100 ]]
+ then
+ echo "We recommend to use more than 4GB disk"
+ exit 0
+ fi
+
+ echo "========================================"
+ echo "Label dev size"
+ echo "========================================"
+ echo $BOOT" " $DISK"1 " $BOOT_SZ "MB"
+ echo $ROOTFS" " $DISK"2 " $ROOTFS_SZ "MB"
+ echo $SYSTEMDATA" " $DISK"3 " $DATA_SZ "MB"
+ echo "[Extend]"" " $DISK"4"
+ echo " "$USER" " $DISK"5 " $USER_SZ "MB"
+ echo " "$MODULE" " $DISK"6 " $MODULE_SZ "MB"
+ echo " "$RAMDISK" " $DISK"7 " $RAMDISK_SZ "MB"
+ echo " "$RAMDISK_RECOVERY" " $DISK"8 " $RAMDISK_RECOVERY_SZ "MB"
+ echo " "$RESERVED0" " $DISK"9 " $RESERVED0_SZ "MB"
+ echo " "$RESERVED1" " $DISK"10 " $RESERVED1_SZ "MB"
+ echo " "$RESERVED2" " $DISK"11 " $RESERVED2_SZ "MB"
+
+ local MOUNT_LIST=`mount | grep $DISK | awk '{print $1}'`
+ for mnt in $MOUNT_LIST
+ do
+ umount $mnt
+ done
+
+ if [ $sfdisk_new == 1 ]; then
+ sfdisk $DISK <<-__EOF__
+ 4MiB,${BOOT_SZ}MiB,0xE,*
+ 8MiB,${ROOTFS_SZ}MiB,,-
+ 8MiB,${DATA_SZ}MiB,,-
+ 8MiB,,E,-
+ ,${USER_SZ}MiB,,-
+ ,${MODULE_SZ}MiB,,-
+ ,${RAMDISK_SZ}MiB,,-
+ ,${RAMDISK_RECOVERY_SZ}MiB,,-
+ ,${RESERVED0_SZ}MiB,,-
+ ,${RESERVED1_SZ}MiB,,-
+ ,${RESERVED2_SZ}MiB,,-
+ __EOF__
+ else
+ # calculate start positions for alignment for extended partitions
+ let "USER_START = 4 + $BOOT_SZ + $ROOTFS_SZ + $DATA_SZ + 1"
+ let "MODULE_START = $USER_START + $USER_SZ + 1"
+ let "RAMDISK_START = $MODULE_START + $MODULE_SZ + 1"
+ let "RAMDISK_RECOVERY_START = $RAMDISK_START + $RAMDISK_SZ + 1"
+ let "RESERVED0_START = $RAMDISK_RECOVERY_START + $RAMDISK_RECOVERY_SZ + 1"
+ let "RESERVED1_START = $RESERVED0_START + $RESERVED0_SZ + 1"
+ let "RESERVED2_START = $RESERVED1_START + $RESERVED1_SZ + 1"
+
+ sfdisk --in-order --Linux --unit M $DISK <<-__EOF__
+ 4,$BOOT_SZ,0xE,*
+ ,$ROOTFS_SZ,,-
+ ,$DATA_SZ,,-
+ ,,E,-
+ $USER_START,$USER_SZ,,-
+ $MODULE_START,$MODULE_SZ,,-
+ $RAMDISK_START,$RAMDISK_SZ,,-
+ $RAMDISK_RECOVERY_START,$RAMDISK_RECOVERY_SZ,,-
+ $RESERVED0_START,$RESERVED0_SZ,,-
+ $RESERVED1_START,$RESERVED1_SZ,,-
+ $RESERVED2_START,$RESERVED2_SZ,,-
+ __EOF__
+ fi
+
+ local -r PART1=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]1\$"`
+ mkfs.vfat -F 16 ${PART1} -n $BOOT
+
+ local -r PART2=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]2\$"`
+ mkfs.ext4 -q ${PART2} -L $ROOTFS -F
+
+ local -r PART3=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]3\$"`
+ mkfs.ext4 -q ${PART3} -L $SYSTEMDATA -F
+
+ local -r PART5=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]5\$"`
+ mkfs.ext4 -q ${PART5} -L $USER -F
+
+ local -r PART6=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]6\$"`
+ mkfs.ext4 -q ${PART6} -L $MODULE -F
+
+ local -r PART7=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]7\$"`
+ mkfs.ext4 -q ${PART7} -L $RAMDISK -F
+
+ local -r PART8=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]8\$"`
+ mkfs.ext4 -q ${PART8} -L $RAMDISK_RECOVERY -F
+
+ local -r PART9=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]9\$"`
+ mkfs.ext4 -q ${PART9} -L $RESERVED0 -F
+
+ local -r PART10=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]10\$"`
+ mkfs.ext4 -q ${PART10} -L $RESERVED1 -F
+
+ local -r PART11=/dev/`lsblk ${DISK} -o KNAME | grep -G "[a-z]11\$"`
+ mkfs.ext4 -q ${PART11} -L $RESERVED2 -F
+}
+
+function show_usage () {
+ echo "- Usage:"
+ echo " sudo ./sd_fusing*.sh -d <device> [-b <path> <path> ..] [--format]"
+}
+
+function check_partition_format () {
+ if [ "$FORMAT" != "2" ]; then
+ echo "-----------------------"
+ echo "Skip $DEVICE format"
+ echo "-----------------------"
+ return 0
+ fi
+
+ echo "-------------------------------"
+ echo "Start $DEVICE format"
+ echo ""
+ mkpart_3
+ echo "End $DEVICE format"
+ echo "-------------------------------"
+ echo ""
+}
+
+function check_args () {
+ if [ "$DEVICE" == "" ]; then
+ echo "$(tput setaf 1)$(tput bold)- Device node is empty!"
+ show_usage
+ tput sgr 0
+ exit 0
+ fi
+
+ if [ "$DEVICE" != "" ]; then
+ echo "Device: $DEVICE"
+ fi
+
+ if [ "$FUSING_BINARY_NUM" != 0 ]; then
+ echo "Fusing binary: "
+ for ((bid = 0 ; bid < $FUSING_BINARY_NUM ; bid++))
+ do
+ echo " ${FUSING_BINARY_ARRAY[bid]}"
+ done
+ echo ""
+ fi
+
+ if [ "$FORMAT" == "1" ]; then
+ echo ""
+ echo "$(tput setaf 3)$(tput bold)$DEVICE will be formatted, Is it OK? [y/n]"
+ tput sgr 0
+ read input
+ if [ "$input" == "y" ] || [ "$input" == "Y" ]; then
+ FORMAT=2
+ else
+ FORMAT=0
+ fi
+ fi
+}
+
+function check_device () {
+ if [ ! -b "$DEVICE" ]; then
+ echo "No such device: $DEVICE"
+ exit 0
+ fi
+
+ local REMOVABLE=`lsblk $DEVICE -nd -o RM | grep 1 | wc -l`
+ if [ "$REMOVABLE" == "0" ]; then
+ echo ""
+ echo "$(tput setaf 3)$(tput bold)$DEVICE is not a removable disk, Is it OK? [y/<n>]"
+ tput sgr 0
+ read input
+ if [ "$input" != "y" ] && [ "$input" != "Y" ]; then
+ exit 0
+ fi
+ fi
+
+ if [ ! -w "$DEVICE" ]; then
+ echo "Write not permitted: $DEVICE"
+ exit 0
+ fi
+}
+
+function print_logo () {
+ echo ""
+ echo "Khadas VIM3 downloader, version 1.0"
+ echo ""
+}
+
+print_logo
+
+function add_fusing_binary() {
+ local declare binary_name=$1
+ FUSING_BINARY_ARRAY[$FUSING_BINARY_NUM]=$binary_name
+
+ FUSING_BINARY_NUM=$((FUSING_BINARY_NUM + 1))
+}
+
+
+declare -i binary_option=0
+
+while test $# -ne 0; do
+ option=$1
+ shift
+
+ case $option in
+ --f | --format)
+ FORMAT="1"
+ binary_option=0
+ ;;
+ -d)
+ DEVICE=$1
+ binary_option=0
+ shift
+ ;;
+ -b)
+ add_fusing_binary $1
+ binary_option=1
+ shift
+ ;;
+ *)
+ if [ $binary_option == 1 ];then
+ add_fusing_binary $option
+ else
+ echo "Unkown command: $option"
+ exit
+ fi
+ ;;
+ esac
+done
+
+check_args
+check_device
+check_partition_format
+check_ddversion
+fuse_image