scripts: Add support for cereating images for use with QEMU.
[platform/kernel/u-boot.git] / scripts / tizen / sd_fusing_vf2.sh
1 #!/bin/bash
2
3 declare CREATE=""
4 declare DEVICE=""
5 declare FILE=""
6 declare FORMAT=""
7 declare LOOP_SIZE="8192"
8 declare -i OLD_DD=0
9
10 # Binaires array for fusing
11 declare -a FUSING_BINARY_ARRAY
12 declare -i FUSING_BINARY_NUM=0
13
14 declare CONV_ASCII=""
15 declare -i FUS_ENTRY_NUM=0
16 declare -i ab_option=0
17
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
31         )
32
33 declare -r -i PART_TABLE_COL=5
34 declare -r -i PART_TABLE_ROW=${#PART_TABLE[*]}/${PART_TABLE_COL}
35
36 # tear down loopback device on exit
37 trap 'test -n "$FILE" && losetup -d "$DEVICE"' EXIT
38
39 # partition table support
40 function get_index_use_name () {
41         local -r binary_name=$1
42
43         for ((idx=0;idx<$PART_TABLE_ROW;idx++)); do
44                 if [ ${PART_TABLE[idx * ${PART_TABLE_COL} + 0]} == "$binary_name" ]; then
45                         return $idx
46                 fi
47         done
48
49         # return out of bound index
50         return $idx
51 }
52
53 function print_message () {
54         local color=$1
55         local message=$2
56
57         tput setaf $color
58         tput bold
59         echo ""
60         echo $message
61         tput sgr 0
62 }
63
64 function check_ddversion () {
65         # NOTE
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]}
72
73         if [ $major -lt 8 ];  then
74                 OLD_DD=1
75         elif [ $major -eq 8 -a $minor -lt 24 ];  then
76                 OLD_DD=1
77         fi
78 }
79
80 function fusing_image () {
81         local -r fusing_img=$1
82
83         # get binary info using basename
84         get_index_use_name $(basename "$fusing_img")
85         local -r -i part_idx=$?
86
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
90                         local -r blktype=disk
91                 else
92                         local -r blktype=part
93                 fi
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]}
96         else
97                 echo "Unsupported binary: $fusing_img"
98                 return
99         fi
100
101         local -r input_size=`du -b $fusing_img | awk '{print $1}'`
102         local -r input_size_mb=`expr $input_size / 1024 / 1024`
103
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
108                         umount $device
109                 fi
110         fi
111         if [ $OLD_DD == 1 ]; then
112                 dd if=$fusing_img | pv -s $input_size | dd of=$device bs=$bs
113         else
114                 dd if=$fusing_img of=$device bs=$bs status=progress oflag=direct
115         fi
116 }
117
118 function fuse_image_tarball () {
119         local -r filepath=$1
120         local -r temp_dir="tar_tmp"
121
122         mkdir -p $temp_dir
123         tar xvf $filepath -C $temp_dir
124         cd $temp_dir
125
126         for file in *
127         do
128                 fusing_image $file
129         done
130
131         cd ..
132         rm -rf $temp_dir
133         eval sync
134 }
135
136 function fuse_image () {
137
138         if [ "$FUSING_BINARY_NUM" == 0 ]; then
139                 return
140         fi
141
142         for ((fuse_idx = 0 ; fuse_idx < $FUSING_BINARY_NUM ; fuse_idx++))
143         do
144                 local filename=${FUSING_BINARY_ARRAY[fuse_idx]}
145
146                 case "$filename" in
147                     *.tar | *.tar.gz)
148                         fuse_image_tarball $filename
149                         ;;
150                     *)
151                         fusing_image $filename
152                         ;;
153                 esac
154         done
155         echo ""
156 }
157
158 # partition format
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__
162
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]}
168         local sfdisk_new=0
169         local support_delete=0
170
171         if [ $major -gt 2 ];  then
172                 sfdisk_new=1
173                 if [ $major -eq 2 -a $minor -ge 28 ]; then
174                         support_delete=1
175                 fi
176         else
177                 if [ $major -eq 2 -a $minor -ge 26 ];  then
178                         sfdisk_new=1
179                 fi
180         fi
181
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!"
184                 tput sgr 0
185                 exit -1
186         fi
187
188         local -r DISK=$DEVICE
189         local -r SIZE=`sfdisk -s $DISK`
190         local -r SIZE_MB=$((SIZE >> 10))
191
192         local -r SPL_SZ=2
193         local -r UBOOT_SZ=4
194         local -r BOOT_SZ=292
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
200         local -r INFORM_SZ=8
201         local -r HAL_SZ=256
202         local -r PARAM_SZ=4
203         local -r DATA_SIZE=1344
204         local -r RESERVED1_SZ=64
205         local -r RESERVED2_SZ=125
206         local -r EXTEND_SZ=36
207
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"
209
210         local -r SPL=spl
211         local -r UBOOT=uboot
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
224
225         if [[ $USER_SZ -le 100 ]]
226         then
227                 echo "We recommend to use more than 8GB disk"
228                 exit 0
229         fi
230
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"
249
250         local MOUNT_LIST=`mount | grep $DISK | awk '{print $1}'`
251         for mnt in $MOUNT_LIST
252         do
253                 umount $mnt
254         done
255
256         echo "Remove partition table..."
257         dd if=/dev/zero of=$DISK bs=512 count=32 conv=notrunc
258
259         if [ $support_delete == 1 ]; then
260                 sfdisk --delete $DISK
261         fi
262
263         SCRIPT=""
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]}"
267         done
268
269         sfdisk $DISK <<-__EOF__
270         label: gpt
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
286         __EOF__
287
288
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"
295                                 exit -1
296                         fi
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
299                 else
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]}"
301                 fi
302         done
303 }
304
305 function show_usage () {
306         echo "- 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"
310         echo "  -b       : binary"
311         echo "  -s       : size of the loopback device to create in MiB"
312 }
313
314 function check_partition_format () {
315         if [ "$FORMAT" != "2" ]; then
316                 echo "-----------------------"
317                 echo "Skip $DEVICE format"
318                 echo "-----------------------"
319                 return 0
320         fi
321
322         echo "-------------------------------"
323         echo "Start $DEVICE format"
324         echo ""
325         mkpart_3
326         echo "End $DEVICE format"
327         echo "-------------------------------"
328         echo ""
329 }
330
331 function check_args () {
332         if [ "$DEVICE" == "" ]; then
333                 echo "$(tput setaf 1)$(tput bold)- Device node is empty!"
334                 show_usage
335                 tput sgr 0
336                 exit 0
337         fi
338
339         if [ "$DEVICE" != "" ]; then
340                 echo "Device: $DEVICE"
341         fi
342
343         if [ "$FUSING_BINARY_NUM" != 0 ]; then
344                 echo "Fusing binary: "
345                 for ((bid = 0 ; bid < $FUSING_BINARY_NUM ; bid++))
346                 do
347                         echo "  ${FUSING_BINARY_ARRAY[bid]}"
348                 done
349                 echo ""
350         fi
351
352         if [ "$FORMAT" == "1" ]; then
353                 echo ""
354                 echo -n "$(tput setaf 3)$(tput bold)$DEVICE will be formatted, Is it OK? [y/<n>] "
355                 tput sgr 0
356                 read input
357                 if [ "$input" == "y" ] || [ "$input" == "Y" ]; then
358                         FORMAT=2
359                 else
360                         FORMAT=0
361                 fi
362         fi
363 }
364
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"
370                         exit -1
371                 fi
372         fi
373         if [ -f "$DEVICE" ]; then
374                 FILE="$DEVICE"
375                 DEVICE=$(losetup --partscan --show --find $FILE)
376                 if [ "$?" != "0" ]; then
377                         echo "Failed to set up the loopback device"
378                         exit -1
379                 fi
380         fi
381
382         if [ ! -b "$DEVICE" ]; then
383                 echo "No such device: $DEVICE"
384                 exit 0
385         fi
386
387         DEVICE=/dev/`lsblk $DEVICE -o TYPE,KNAME | awk '/^(disk|loop)/ { print $2 }'`
388
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
392                 echo ""
393                 echo -n "$(tput setaf 3)$(tput bold)$DEVICE is neither a removable disk nor a loopback, Is it OK? [y/<n>] "
394                 tput sgr 0
395                 read input
396                 if [ "$input" != "y" ] && [ "$input" != "Y" ]; then
397                         exit 0
398                 fi
399         fi
400
401         if [ ! -w "$DEVICE" ]; then
402                 echo "Write not permitted: $DEVICE"
403                 exit 0
404         fi
405 }
406
407 function print_logo () {
408         echo ""
409         echo "For VisionFive2 and QEMU, version 1.1.0"
410         echo ""
411 }
412
413 print_logo
414
415 function add_fusing_binary() {
416         local declare binary_name=$1
417
418         if [ "$binary_name" != "" ]; then
419                 if [ -f "$binary_name" ]; then
420                         FUSING_BINARY_ARRAY[$FUSING_BINARY_NUM]=$binary_name
421
422                         FUSING_BINARY_NUM=$((FUSING_BINARY_NUM + 1))
423                 else
424                         echo "No such file: $binary_name"
425                 fi
426         fi
427 }
428
429
430 declare -i binary_option=0
431
432 while test $# -ne 0; do
433         option=$1
434         shift
435
436         case $option in
437         -c | --create)
438                 CREATE="1"
439                 set -- -f "${@}"
440                 binary_option=0
441                 ;;
442         -f | --format)
443                 FORMAT="1"
444                 binary_option=0
445                 ;;
446         -d)
447                 DEVICE=$1
448                 binary_option=0
449                 shift
450                 ;;
451         -b)
452                 add_fusing_binary $1
453                 binary_option=1
454                 shift
455                 ;;
456         -s)
457                 LOOP_SIZE=$1
458                 binary_option=0
459                 shift
460                 ;;
461         *)
462                 if [ $binary_option == 1 ];then
463                         add_fusing_binary $option
464                 else
465                         echo "Unkown command: $option"
466                         exit
467                 fi
468                 ;;
469         esac
470 done
471
472 check_args
473 check_device
474 check_partition_format
475 check_ddversion
476 fuse_image