8 # Binaires array for fusing
9 declare -a FUSING_BINARY_ARRAY
10 declare -i FUSING_BINARY_NUM=0
13 declare -i FUS_ENTRY_NUM=0
14 declare -i ab_option=0
16 # binary name | part number | bs | label | fs type
17 declare -a PART_TABLE=(
18 "boot.img" 1 4M boot_a vfat
19 "rootfs.img" 2 4M rootfs_a ext4
20 "system-data.img" 3 4M system-data ext4
21 "user.img" 5 4M user ext4
22 "modules.img" 6 4M module_a ext4
23 "ramdisk.img" 7 4M ramdisk_a ext4
24 "ramdisk-recovery.img" 8 4M ramdisk-recovery_a ext4
25 "hal.img" 10 4M hal_a ext4
26 "boot.img" 11 4M boot_b vfat
27 "rootfs.img" 12 4M rootfs_b ext4
28 "modules.img" 13 4M module_b ext4
29 "ramdisk.img" 14 4M ramdisk_b ext4
30 "ramdisk-recovery.img" 15 4M ramdisk-recovery_b ext4
31 "hal.img" 16 4M hal_b ext4
33 declare -a PART_TABLE_B=(
34 "boot.img" 11 4M boot_b vfat
35 "rootfs.img" 12 4M rootfs_b ext4
36 "modules.img" 13 4M module_b ext4
37 "ramdisk.img" 14 4M ramdisk_b ext4
38 "ramdisk-recovery.img" 15 4M ramdisk-recovery_b ext4
39 "hal.img" 16 4M hal_b ext4
42 declare -r -i PART_TABLE_COL=5
43 declare -r -i PART_TABLE_ROW=${#PART_TABLE[*]}/${PART_TABLE_COL}
44 declare -r -i PART_TABLE_ROW_B=${#PART_TABLE_B[*]}/${PART_TABLE_COL}
46 # partition table support
47 function get_index_use_name () {
48 local -r binary_name=$1
50 for ((idx=0;idx<$PART_TABLE_ROW;idx++)); do
51 if [ ${PART_TABLE[idx * ${PART_TABLE_COL} + 0]} == "$binary_name" ]; then
56 # return out of bound index
60 # partition table support
61 function get_index_use_name_to_b () {
62 local -r binary_name=$1
64 for ((idx=0;idx<$PART_TABLE_ROW_B;idx++)); do
65 if [ ${PART_TABLE_B[idx * ${PART_TABLE_COL} + 0]} == "$binary_name" ]; then
70 # return out of bound index
74 function print_message () {
85 function check_ddversion () {
87 # before coreutils dd 8.24, dd doesn't support "status=progress"
88 # and the option causes fusing failure. For backward compatibility,
89 # do not use the option for old dd
90 local version=(`dd --version | head -1 | grep -o '[0-9]\+'`)
91 local major=${version[0]}
92 local minor=${version[1]}
94 if [ $major -lt 8 ]; then
96 elif [ $major -eq 8 -a $minor -lt 24 ]; then
101 function fusing_image () {
102 if [ $ab_option == 2 ] ; then
103 echo "Skip to update Partitoin A"
106 local -r fusing_img=$1
108 # get binary info using basename
109 get_index_use_name $(basename "$fusing_img")
110 local -r -i part_idx=$?
112 if [ $part_idx -ne $PART_TABLE_ROW ];then
113 local -r num=${PART_TABLE[${part_idx} * ${PART_TABLE_COL} + 1]}
114 if [ "${num}" == "" ]; then
115 local -r blktype=disk
117 local -r blktype=part
119 local -r device=/dev/`lsblk ${DEVICE} -o TYPE,KNAME | awk "/^${blktype}.*[a-z]${num}\$/ { print \\\$2 }"`
120 local -r bs=${PART_TABLE[${part_idx} * ${PART_TABLE_COL} + 2]}
122 echo "Unsupported binary: $fusing_img"
126 local -r input_size=`du -b $fusing_img | awk '{print $1}'`
127 local -r input_size_mb=`expr $input_size / 1024 / 1024`
129 print_message 2 "[Fusing $1 ($input_size_mb MiB)]"
130 if [ "$blktype" == "part" ]; then
131 local MOUNT_PART=`mount | grep $device`
132 if [ "$MOUNT_PART" != "" ]; then
136 if [ $OLD_DD == 1 ]; then
137 dd if=$fusing_img | pv -s $input_size | dd of=$device bs=$bs
139 dd if=$fusing_img of=$device bs=$bs status=progress oflag=direct
143 function fusing_image_to_b () {
144 if [ $ab_option == 0 ] ; then
145 echo "Skip to update Partitoin B"
148 local -r fusing_img=$1
150 # get binary info using basename
151 get_index_use_name_to_b $(basename "$fusing_img")
153 local -r -i part_idx=$?
155 if [ $part_idx -ne $PART_TABLE_ROW_B ];then
156 local -r num=${PART_TABLE_B[${part_idx} * ${PART_TABLE_COL} + 1]}
157 if [ "${num}" == "" ]; then
158 local -r blktype=disk
160 local -r blktype=part
162 local -r device=/dev/`lsblk ${DEVICE} -o TYPE,KNAME | awk "/^${blktype}.*[a-z]${num}\$/ { print \\\$2 }"`
163 local -r bs=${PART_TABLE_B[${part_idx} * ${PART_TABLE_COL} + 2]}
165 echo "Unsupported binary: $fusing_img"
169 local -r input_size=`du -b $fusing_img | awk '{print $1}'`
170 local -r input_size_mb=`expr $input_size / 1024 / 1024`
172 print_message 2 "[Fusing $1 ($input_size_mb MiB)]"
173 if [ "$blktype" == "part" ]; then
174 local MOUNT_PART=`mount | grep $device`
175 if [ "$MOUNT_PART" != "" ]; then
179 if [ $OLD_DD == 1 ]; then
180 dd if=$fusing_img | pv -s $input_size | dd of=$device bs=$bs
182 dd if=$fusing_img of=$device bs=$bs status=progress oflag=direct
186 function fuse_image_tarball () {
188 local -r temp_dir="tar_tmp"
191 tar xvf $filepath -C $temp_dir
197 fusing_image_to_b $file
205 function initialize_parameter () {
206 # create "reboot-param.bin" file in inform partition for passing reboot parameter
207 # It should be done only once upon partition format.
208 local -r DISK=$DEVICE
209 local -r PART9=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]9\$"`
211 if [ -d mnt_tmp ]; then
212 echo "Remove the existing mnt_tmp directory!!"
216 mount -t ext4 ${PART9} ./mnt_tmp
217 echo "norm" > ./mnt_tmp/reboot-param.bin
218 echo "norm" > ./mnt_tmp/reboot-param.info
219 echo "a" > ./mnt_tmp/partition-ab.info
220 echo "1" > ./mnt_tmp/partition-ab-cloned.info
221 echo "0" > ./mnt_tmp/upgrade-status.info
223 # To check the status of partition. (default "ok")
224 echo "ok" > ./mnt_tmp/partition-a-status.info
225 echo "ok" > ./mnt_tmp/partition-b-status.info
232 function fuse_image () {
234 if [ "$FUSING_BINARY_NUM" == 0 ]; then
238 # Clear preivous values before flashing image
241 for ((fuse_idx = 0 ; fuse_idx < $FUSING_BINARY_NUM ; fuse_idx++))
243 local filename=${FUSING_BINARY_ARRAY[fuse_idx]}
247 fuse_image_tarball $filename
250 fusing_image $filename
251 fusing_image_to_b $filename
259 function mkpart_3 () {
260 # NOTE: if your sfdisk version is less than 2.26.0, then you should use following sfdisk command:
261 # sfdisk --in-order --Linux --unit M $DISK <<-__EOF__
263 # NOTE: sfdisk 2.26 doesn't support units other than sectors and marks --unit option as deprecated.
264 # The input data needs to contain multipliers (MiB) instead.
265 local version=(`sfdisk -v | grep -o '[0-9]\+'`)
266 local major=${version[0]}
267 local minor=${version[1]}
269 local support_delete=0
271 if [ $major -gt 2 ]; then
273 if [ $major -eq 2 -a $minor -ge 28 ]; then
277 if [ $major -eq 2 -a $minor -ge 26 ]; then
282 if [ $sfdisk_new == 0 ]; then
283 echo "$(tput setaf 3)$(tput bold)NOTICE: Your sfdisk ${version[0]}.${version[1]} version is too old. Update Latest sfdisk!"
288 local -r DISK=$DEVICE
289 local -r SIZE=`sfdisk -s $DISK`
290 local -r SIZE_MB=$((SIZE >> 10))
293 local -r ROOTFS_SZ=3072
294 local -r DATA_SZ=1344
295 local -r MODULE_SZ=32
296 local -r RAMDISK_SZ=32
297 local -r RAMDISK_RECOVERY_SZ=32
301 local -r RESERVED1_SZ=64
302 local -r RESERVED2_SZ=125
303 local -r EXTEND_SZ=36
305 let "USER_SZ = $SIZE_MB - $BOOT_SZ * 2 - $ROOTFS_SZ * 2 - $DATA_SZ - $MODULE_SZ * 2 - $RAMDISK_SZ * 2 - $RAMDISK_RECOVERY_SZ * 2 - $INFORM_SZ - $EXTEND_SZ - $HAL_SZ * 2 - $RESERVED1_SZ - $RESERVED2_SZ - $PARAM_SZ"
307 local -r BOOT_A=${PART_TABLE[0 * ${PART_TABLE_COL} + 3]}
308 local -r ROOTFS_A=${PART_TABLE[1 * ${PART_TABLE_COL} + 3]}
309 local -r SYSTEMDATA=${PART_TABLE[2 * ${PART_TABLE_COL} + 3]}
310 local -r USER=${PART_TABLE[3 * ${PART_TABLE_COL} + 3]}
311 local -r MODULE_A=${PART_TABLE[4 * ${PART_TABLE_COL} + 3]}
312 local -r RAMDISK_A=${PART_TABLE[5 * ${PART_TABLE_COL} + 3]}
313 local -r RAMDISK_RECOVERY_A=${PART_TABLE[6 * ${PART_TABLE_COL} + 3]}
314 local -r INFORM=inform
315 local -r HAL_A=${PART_TABLE[7 * ${PART_TABLE_COL} + 3]}
316 local -r BOOT_B=${PART_TABLE[8 * ${PART_TABLE_COL} + 3]}
317 local -r ROOTFS_B=${PART_TABLE[9 * ${PART_TABLE_COL} + 3]}
318 local -r MODULE_B=${PART_TABLE[10 * ${PART_TABLE_COL} + 3]}
319 local -r RAMDISK_B=${PART_TABLE[11 * ${PART_TABLE_COL} + 3]}
320 local -r RAMDISK_RECOVERY_B=${PART_TABLE[12 * ${PART_TABLE_COL} + 3]}
321 local -r HAL_B=${PART_TABLE[13 * ${PART_TABLE_COL} + 3]}
322 local -r RESERVED0=reserved0
323 local -r RESERVED1=reserved1
324 local -r RESERVED2=reserved2
326 if [[ $USER_SZ -le 100 ]]
328 echo "We recommend to use more than 8GB disk"
332 echo "================================================"
333 echo "Label dev size"
334 echo "================================================"
335 echo $BOOT_A" " $DISK"1 " $BOOT_SZ "MB"
336 echo $ROOTFS_A" " $DISK"2 " $ROOTFS_SZ "MB"
337 echo $SYSTEMDATA" " $DISK"3 " $DATA_SZ "MB"
338 echo "[Extend]"" " $DISK"4"
339 echo " "$USER" " $DISK"5 " $USER_SZ "MB"
340 echo " "$MODULE_A" " $DISK"6 " $MODULE_SZ "MB"
341 echo " "$RAMDISK_A" " $DISK"7 " $RAMDISK_SZ "MB"
342 echo " "$RAMDISK_RECOVERY_A" " $DISK"8 " $RAMDISK_RECOVERY_SZ "MB"
343 echo " "$INFORM" " $DISK"9 " $INFORM_SZ "MB"
344 echo " "$HAL_A" " $DISK"10 " $HAL_SZ "MB"
345 echo " "$BOOT_B" " $DISK"11 " $BOOT_SZ "MB"
346 echo " "$ROOTFS_B" " $DISK"12 " $ROOTFS_SZ "MB"
347 echo " "$MODULE_B" " $DISK"13 " $MODULE_SZ "MB"
348 echo " "$RAMDISK_B" " $DISK"14 " $RAMDISK_SZ "MB"
349 echo " "$RAMDISK_RECOVERY_B" " $DISK"15 " $RAMDISK_RECOVERY_SZ "MB"
350 echo " "$HAL_B" " $DISK"16 " $HAL_SZ "MB"
351 echo " "$RESERVED0" " $DISK"17 " $PARAM_SZ "MB"
352 echo " "$RESERVED1" " $DISK"18 " $RESERVED1_SZ "MB"
353 echo " "$RESERVED2" " $DISK"19 " $RESERVED2_SZ "MB"
355 local MOUNT_LIST=`mount | grep $DISK | awk '{print $1}'`
356 for mnt in $MOUNT_LIST
361 echo "Remove partition table..."
362 dd if=/dev/zero of=$DISK bs=512 count=32 conv=notrunc
364 if [ $support_delete == 1 ]; then
365 sfdisk --delete $DISK
369 for ((idx=0; idx < $PART_TABLE_ROW; idx++)); do
370 NR=${PART_TABLE[idx * ${PART_TABLE_COL} + 1]}
371 eval "PART_LABEL_NR_${NR}=${PART_TABLE[idx * ${PART_TABLE_COL} + 3]}"
374 sfdisk $DISK <<-__EOF__
376 start=4MiB, size=${BOOT_SZ}MiB, type= C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=${PART_LABEL_NR_1}
377 size=${ROOTFS_SZ}MiB, name=${PART_LABEL_NR_2}
378 size=${DATA_SZ}MiB, name=${PART_LABEL_NR_3}
379 size=${EXTEND_SZ}MiB, name=none
380 size=${USER_SZ}MiB, name=${PART_LABEL_NR_5}
381 size=${MODULE_SZ}MiB, name=${PART_LABEL_NR_6}
382 size=${RAMDISK_SZ}MiB, name=${PART_LABEL_NR_7}
383 size=${RAMDISK_RECOVERY_SZ}MiB, name=${PART_LABEL_NR_8}
384 size=${INFORM_SZ}MiB, name=inform
385 size=${HAL_SZ}MiB, name=${PART_LABEL_NR_10}
386 size=${BOOT_SZ}MiB, type= C12A7328-F81F-11D2-BA4B-00A0C93EC93B, name=${PART_LABEL_NR_11}
387 size=${ROOTFS_SZ}MiB, name=${PART_LABEL_NR_12}
388 size=${MODULE_SZ}MiB, name=${PART_LABEL_NR_13}
389 size=${RAMDISK_SZ}MiB, name=${PART_LABEL_NR_14}
390 size=${RAMDISK_RECOVERY_SZ}MiB, name=${PART_LABEL_NR_15}
391 size=${HAL_SZ}MiB, name=${PART_LABEL_NR_16}
392 size=${PARAM_SZ}MiB, name=reserved0
393 size=${RESERVED1_SZ}MiB, name=reserved1
394 size=${RESERVED2_SZ}MiB, name=reserved2
398 for ((idx=0;idx<$PART_TABLE_ROW;idx++)); do
399 local PART=/dev/`lsblk ${DISK} -o TYPE,KNAME | awk "/^part.*[a-z]${PART_TABLE[$idx * ${PART_TABLE_COL} + 1]}\$/ { print \\\$2 }"`
400 if [ "${PART_TABLE[$idx * ${PART_TABLE_COL} + 4]}" == "vfat" ]; then
401 mkfs.vfat -F 16 ${PART} -n ${PART_TABLE[$idx * ${PART_TABLE_COL} + 3]}
402 if [ $? -eq 1 ]; then
403 echo "Failed to format as FAT filesystem"
406 elif [ "${PART_TABLE[$idx * ${PART_TABLE_COL} + 4]}" == "ext4" ]; then
407 mkfs.ext4 -q ${PART} -L ${PART_TABLE[$idx * ${PART_TABLE_COL} + 3]} -F
409 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]}"
413 local -r PART9=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]9\$"`
414 mkfs.ext4 -q ${PART9} -L $INFORM -F -O ^metadata_csum
416 # initialize value of parameters
419 local -r PART17=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]17\$"`
420 mkfs.ext4 -q ${PART17} -L $RESERVED0 -F
422 local -r PART18=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]18\$"`
423 mkfs.ext4 -q ${PART18} -L $RESERVED1 -F
425 local -r PART19=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]19\$"`
426 mkfs.ext4 -q ${PART19} -L $RESERVED2 -F
429 function skip_resize () {
430 if [ "${SKIP}" == "0" ]; then
434 if [ ! -d mnt_tmp ] ; then
438 mount -t ext4 ${DEVICE}3 ./mnt_tmp
439 touch ./mnt_tmp/var/.resizefs_done
441 echo "Rootfs resize will be skipped..."
447 function show_usage () {
449 echo " sudo ./sd_fusing*.sh -d <device> [-b <path> <path> ..] [--format] [--update [b] ]"
450 echo " -d : device ndoe "
452 echo " --update : If want to update Image about B Partition, use --update option with b"
453 echo " Otherwise, it will be updated to both partition"
456 function check_partition_format () {
457 if [ "$FORMAT" != "2" ]; then
458 echo "-----------------------"
459 echo "Skip $DEVICE format"
460 echo "-----------------------"
464 echo "-------------------------------"
465 echo "Start $DEVICE format"
468 echo "End $DEVICE format"
469 echo "-------------------------------"
473 function check_args () {
474 if [ "$DEVICE" == "" ]; then
475 echo "$(tput setaf 1)$(tput bold)- Device node is empty!"
481 if [ "$DEVICE" != "" ]; then
482 echo "Device: $DEVICE"
485 if [ "$FUSING_BINARY_NUM" != 0 ]; then
486 echo "Fusing binary: "
487 for ((bid = 0 ; bid < $FUSING_BINARY_NUM ; bid++))
489 echo " ${FUSING_BINARY_ARRAY[bid]}"
494 if [ "$FORMAT" == "1" ]; then
496 echo -n "$(tput setaf 3)$(tput bold)$DEVICE will be formatted, Is it OK? [y/<n>] "
499 if [ "$input" == "y" ] || [ "$input" == "Y" ]; then
507 function check_device () {
508 if [ ! -b "$DEVICE" ]; then
509 echo "No such device: $DEVICE"
513 DEVICE=/dev/`lsblk $DEVICE -o TYPE,KNAME | awk '/^(disk|loop)/ { print $2 }'`
515 local REMOVABLE=`lsblk $DEVICE -nd -o RM | grep 1 | wc -l`
516 if [ "$REMOVABLE" == "0" ]; then
518 echo -n "$(tput setaf 3)$(tput bold)$DEVICE is not a removable disk, Is it OK? [y/<n>] "
521 if [ "$input" != "y" ] && [ "$input" != "Y" ]; then
526 if [ ! -w "$DEVICE" ]; then
527 echo "Write not permitted: $DEVICE"
532 function print_logo () {
534 echo "Raspberry Pi4 downloader, version 1.0.12"
535 echo "$(tput setaf 1)$(tput bold)NOTE: To use this script, it has to update to latest eeprom"
541 function add_fusing_binary() {
542 local declare binary_name=$1
544 if [ "$binary_name" != "" ]; then
545 if [ -f "$binary_name" ]; then
546 FUSING_BINARY_ARRAY[$FUSING_BINARY_NUM]=$binary_name
548 FUSING_BINARY_NUM=$((FUSING_BINARY_NUM + 1))
550 echo "No such file: $binary_name"
556 declare -i binary_option=0
558 while test $# -ne 0; do
578 if [ "$1" == "b" ] ; then
590 if [ $binary_option == 1 ];then
591 add_fusing_binary $option
593 echo "Unkown command: $option"
602 check_partition_format