7 declare LOOP_SIZE="8192"
10 # Binaires array for fusing
11 declare -a FUSING_BINARY_ARRAY
12 declare -i FUSING_BINARY_NUM=0
15 declare -i FUS_ENTRY_NUM=0
16 declare -i ab_option=0
18 # binary name | part number | bs | label | fs type
19 declare -a PART_TABLE=(
20 "u-boot-spl.bin.normal.out" 1 4M SPL raw
21 "u-boot.img" 2 4M u-boot raw
22 "u-boot.itb" 2 4M u-boot raw
23 "boot.img" 3 4M boot_a vfat
24 "rootfs.img" 5 4M rootfs_a ext4
25 "system-data.img" 6 4M system-data ext4
26 "user.img" 7 4M user ext4
27 "modules.img" 8 4M module_a ext4
28 "ramdisk.img" 9 4M ramdisk_a ext4
29 "ramdisk-recovery.img" 10 4M ramdisk-recovery_a ext4
30 "hal.img" 12 4M hal_a ext4
33 declare -r -i PART_TABLE_COL=5
34 declare -r -i PART_TABLE_ROW=${#PART_TABLE[*]}/${PART_TABLE_COL}
36 # tear down loopback device on exit
37 trap 'test -n "$FILE" && losetup -d "$DEVICE"' EXIT
39 # partition table support
40 function get_index_use_name () {
41 local -r binary_name=$1
43 for ((idx=0;idx<$PART_TABLE_ROW;idx++)); do
44 if [ ${PART_TABLE[idx * ${PART_TABLE_COL} + 0]} == "$binary_name" ]; then
49 # return out of bound index
53 function print_message () {
64 function check_ddversion () {
66 # before coreutils dd 8.24, dd doesn't support "status=progress"
67 # and the option causes fusing failure. For backward compatibility,
68 # do not use the option for old dd
69 local version=(`dd --version | head -1 | grep -o '[0-9]\+'`)
70 local major=${version[0]}
71 local minor=${version[1]}
73 if [ $major -lt 8 ]; then
75 elif [ $major -eq 8 -a $minor -lt 24 ]; then
80 function fusing_image () {
81 local -r fusing_img=$1
83 # get binary info using basename
84 get_index_use_name $(basename "$fusing_img")
85 local -r -i part_idx=$?
87 if [ $part_idx -ne $PART_TABLE_ROW ];then
88 local -r num=${PART_TABLE[${part_idx} * ${PART_TABLE_COL} + 1]}
89 if [ "${num}" == "" ]; then
94 local -r device=/dev/`lsblk ${DEVICE} -o TYPE,KNAME | awk "/^${blktype}.*[a-z]${num}\$/ { print \\\$2 }"`
95 local -r bs=${PART_TABLE[${part_idx} * ${PART_TABLE_COL} + 2]}
97 echo "Unsupported binary: $fusing_img"
101 local -r input_size=`du -b $fusing_img | awk '{print $1}'`
102 local -r input_size_mb=`expr $input_size / 1024 / 1024`
104 print_message 2 "[Fusing $1 ($input_size_mb MiB)]"
105 if [ "$blktype" == "part" ]; then
106 local MOUNT_PART=`mount | grep $device`
107 if [ "$MOUNT_PART" != "" ]; then
111 if [ $OLD_DD == 1 ]; then
112 dd if=$fusing_img | pv -s $input_size | dd of=$device bs=$bs
114 dd if=$fusing_img of=$device bs=$bs status=progress oflag=direct
118 function fuse_image_tarball () {
120 local -r temp_dir="tar_tmp"
123 tar xvf $filepath -C $temp_dir
136 function fuse_image () {
138 if [ "$FUSING_BINARY_NUM" == 0 ]; then
142 for ((fuse_idx = 0 ; fuse_idx < $FUSING_BINARY_NUM ; fuse_idx++))
144 local filename=${FUSING_BINARY_ARRAY[fuse_idx]}
148 fuse_image_tarball $filename
151 fusing_image $filename
159 function mkpart_3 () {
160 # NOTE: if your sfdisk version is less than 2.26.0, then you should use following sfdisk command:
161 # sfdisk --in-order --Linux --unit M $DISK <<-__EOF__
163 # NOTE: sfdisk 2.26 doesn't support units other than sectors and marks --unit option as deprecated.
164 # The input data needs to contain multipliers (MiB) instead.
165 local version=(`sfdisk -v | grep -o '[0-9]\+'`)
166 local major=${version[0]}
167 local minor=${version[1]}
169 local support_delete=0
171 if [ $major -gt 2 ]; then
173 if [ $major -eq 2 -a $minor -ge 28 ]; then
177 if [ $major -eq 2 -a $minor -ge 26 ]; then
182 if [ $sfdisk_new == 0 ]; then
183 echo "$(tput setaf 3)$(tput bold)NOTICE: Your sfdisk ${version[0]}.${version[1]} version is too old. Update Latest sfdisk!"
188 local -r DISK=$DEVICE
189 local -r SIZE=`sfdisk -s $DISK`
190 local -r SIZE_MB=$((SIZE >> 10))
195 local -r ROOTFS_SZ=3072
196 local -r DATA_SZ=1344
197 local -r MODULE_SZ=32
198 local -r RAMDISK_SZ=32
199 local -r RAMDISK_RECOVERY_SZ=32
203 local -r DATA_SIZE=1344
204 local -r RESERVED1_SZ=64
205 local -r RESERVED2_SZ=125
206 local -r EXTEND_SZ=36
208 let "USER_SZ = $SIZE_MB - $SPL_SZ - $UBOOT_SZ - $BOOT_SZ - $ROOTFS_SZ - $DATA_SZ - $MODULE_SZ - $RAMDISK_SZ - $RAMDISK_RECOVERY_SZ - $INFORM_SZ - $EXTEND_SZ - $HAL_SZ - $RESERVED1_SZ - $RESERVED2_SZ - $PARAM_SZ"
212 local -r BOOT_A=${PART_TABLE[0 * ${PART_TABLE_COL} + 3]}
213 local -r ROOTFS_A=${PART_TABLE[1 * ${PART_TABLE_COL} + 3]}
214 local -r SYSTEMDATA=${PART_TABLE[2 * ${PART_TABLE_COL} + 3]}
215 local -r USER=${PART_TABLE[3 * ${PART_TABLE_COL} + 3]}
216 local -r MODULE_A=${PART_TABLE[4 * ${PART_TABLE_COL} + 3]}
217 local -r RAMDISK_A=${PART_TABLE[5 * ${PART_TABLE_COL} + 3]}
218 local -r RAMDISK_RECOVERY_A=${PART_TABLE[6 * ${PART_TABLE_COL} + 3]}
219 local -r INFORM=inform
220 local -r HAL_A=${PART_TABLE[7 * ${PART_TABLE_COL} + 3]}
221 local -r RESERVED0=reserved0
222 local -r RESERVED1=reserved1
223 local -r RESERVED2=reserved2
225 if [[ $USER_SZ -le 100 ]]
227 echo "We recommend to use more than 8GB disk"
231 echo "================================================"
232 echo "Label dev size"
233 echo "================================================"
234 echo $SPL" " $DISK"1 " $SPL_SZ "MB"
235 echo $UBOOT" " $DISK"2 " $UBOOT_SZ "MB"
236 echo $BOOT_A" " $DISK"3 " $BOOT_SZ "MB"
237 echo "[Extend]"" " $DISK"4"
238 echo " "$SYSTEMDATA" " $DISK"5 " $DATA_SZ "MB"
239 echo " "$ROOTFS_A" " $DISK"6 " $ROOTFS_SZ "MB"
240 echo " "$USER" " $DISK"7 " $USER_SZ "MB"
241 echo " "$MODULE_A" " $DISK"8 " $MODULE_SZ "MB"
242 echo " "$RAMDISK_A" " $DISK"9 " $RAMDISK_SZ "MB"
243 echo " "$RAMDISK_RECOVERY_A" " $DISK"10 " $RAMDISK_RECOVERY_SZ "MB"
244 echo " "$INFORM" " $DISK"11 " $INFORM_SZ "MB"
245 echo " "$HAL_A" " $DISK"12 " $HAL_SZ "MB"
246 echo " "$RESERVED0" " $DISK"13 " $PARAM_SZ "MB"
247 echo " "$RESERVED1" " $DISK"14 " $RESERVED1_SZ "MB"
248 echo " "$RESERVED2" " $DISK"15 " $RESERVED2_SZ "MB"
250 local MOUNT_LIST=`mount | grep $DISK | awk '{print $1}'`
251 for mnt in $MOUNT_LIST
256 echo "Remove partition table..."
257 dd if=/dev/zero of=$DISK bs=512 count=32 conv=notrunc
259 if [ $support_delete == 1 ]; then
260 sfdisk --delete $DISK
264 for ((idx=0; idx < $PART_TABLE_ROW; idx++)); do
265 NR=${PART_TABLE[idx * ${PART_TABLE_COL} + 1]}
266 eval "PART_LABEL_NR_${NR}=${PART_TABLE[idx * ${PART_TABLE_COL} + 3]}"
269 sfdisk $DISK <<-__EOF__
271 start=4MiB, type= 2E54B353-1271-4842-806F-E436D6AF6985, size=${SPL_SZ}MiB, name=spl
272 size=${UBOOT_SZ}MiB, type=5B193300-FC78-40CD-8002-E86C45580B47, name=uboot
273 size=${BOOT_SZ}MiB, type= C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=${PART_LABEL_NR_3}
274 size=${EXTEND_SZ}MiB, name=none
275 size=${ROOTFS_SZ}MiB, name=${PART_LABEL_NR_5}
276 size=${DATA_SZ}MiB, name=${PART_LABEL_NR_6}
277 size=${USER_SZ}MiB, name=${PART_LABEL_NR_7}
278 size=${MODULE_SZ}MiB, name=${PART_LABEL_NR_8}
279 size=${RAMDISK_SZ}MiB, name=${PART_LABEL_NR_9}
280 size=${RAMDISK_RECOVERY_SZ}MiB, name=${PART_LABEL_NR_10}
281 size=${INFORM_SZ}MiB, name=inform
282 size=${HAL_SZ}MiB, name=${PART_LABEL_NR_12}
283 size=${PARAM_SZ}MiB, name=reserved0
284 size=${RESERVED1_SZ}MiB, name=reserved1
285 size=${RESERVED2_SZ}MiB, name=reserved2
289 for ((idx=0;idx<$PART_TABLE_ROW;idx++)); do
290 local PART=/dev/`lsblk ${DISK} -o TYPE,KNAME | awk "/^part.*[a-z]${PART_TABLE[$idx * ${PART_TABLE_COL} + 1]}\$/ { print \\\$2 }"`
291 if [ "${PART_TABLE[$idx * ${PART_TABLE_COL} + 4]}" == "vfat" ]; then
292 mkfs.vfat -F 16 ${PART} -n ${PART_TABLE[$idx * ${PART_TABLE_COL} + 3]}
293 if [ $? -eq 1 ]; then
294 echo "Failed to format as FAT filesystem"
297 elif [ "${PART_TABLE[$idx * ${PART_TABLE_COL} + 4]}" == "ext4" ]; then
298 mkfs.ext4 -q ${PART} -L ${PART_TABLE[$idx * ${PART_TABLE_COL} + 3]} -F
300 echo "Skip to format for unknown filesystem type ${PART_TABLE[$idx * ${PART_TABLE_COL} + 4]} for part$idx, ${PART_TABLE[$idx * ${PART_TABLE_COL} + 3]}"
305 function show_usage () {
307 echo " sudo ./sd_fusing*.sh -d <device> [-b <path> <path> ..] [--format] [--create]"
308 echo " --create : create the backing file and format the loopback device"
309 echo " -d : device node or loopback backing file"
311 echo " -s : size of the loopback device to create in MiB"
314 function check_partition_format () {
315 if [ "$FORMAT" != "2" ]; then
316 echo "-----------------------"
317 echo "Skip $DEVICE format"
318 echo "-----------------------"
322 echo "-------------------------------"
323 echo "Start $DEVICE format"
326 echo "End $DEVICE format"
327 echo "-------------------------------"
331 function check_args () {
332 if [ "$DEVICE" == "" ]; then
333 echo "$(tput setaf 1)$(tput bold)- Device node is empty!"
339 if [ "$DEVICE" != "" ]; then
340 echo "Device: $DEVICE"
343 if [ "$FUSING_BINARY_NUM" != 0 ]; then
344 echo "Fusing binary: "
345 for ((bid = 0 ; bid < $FUSING_BINARY_NUM ; bid++))
347 echo " ${FUSING_BINARY_ARRAY[bid]}"
352 if [ "$FORMAT" == "1" ]; then
354 echo -n "$(tput setaf 3)$(tput bold)$DEVICE will be formatted, Is it OK? [y/<n>] "
357 if [ "$input" == "y" ] || [ "$input" == "Y" ]; then
365 function check_device () {
366 if [ ! -e "$DEVICE" -a "$CREATE" == "1" ]; then
367 dd if=/dev/zero of="$DEVICE" conv=sparse bs=1M count=$LOOP_SIZE
368 if [ "$?" != "0" ]; then
369 echo "Failed to create the backing file"
373 if [ -f "$DEVICE" ]; then
375 DEVICE=$(losetup --partscan --show --find $FILE)
376 if [ "$?" != "0" ]; then
377 echo "Failed to set up the loopback device"
382 if [ ! -b "$DEVICE" ]; then
383 echo "No such device: $DEVICE"
387 DEVICE=/dev/`lsblk $DEVICE -o TYPE,KNAME | awk '/^(disk|loop)/ { print $2 }'`
389 local REMOVABLE=`lsblk $DEVICE -nd -o RM | grep 1 | wc -l`
390 local LOOPBACK=`lsblk $DEVICE -nd -o TYPE | grep loop | wc -l`
391 if [ "$REMOVABLE" == "0" -a "$LOOPBACK" == "0" ]; then
393 echo -n "$(tput setaf 3)$(tput bold)$DEVICE is neither a removable disk nor a loopback, Is it OK? [y/<n>] "
396 if [ "$input" != "y" ] && [ "$input" != "Y" ]; then
401 if [ ! -w "$DEVICE" ]; then
402 echo "Write not permitted: $DEVICE"
407 function print_logo () {
409 echo "For VisionFive2 and QEMU, version 1.1.0"
415 function add_fusing_binary() {
416 local declare binary_name=$1
418 if [ "$binary_name" != "" ]; then
419 if [ -f "$binary_name" ]; then
420 FUSING_BINARY_ARRAY[$FUSING_BINARY_NUM]=$binary_name
422 FUSING_BINARY_NUM=$((FUSING_BINARY_NUM + 1))
424 echo "No such file: $binary_name"
430 declare -i binary_option=0
432 while test $# -ne 0; do
462 if [ $binary_option == 1 ];then
463 add_fusing_binary $option
465 echo "Unkown command: $option"
474 check_partition_format