0bd2bee891a1183e3316ec3ed4dcbd3a1cac9fbd
[platform/kernel/u-boot.git] / scripts / tizen / sd_fusing_rpi3.sh
1 #!/bin/bash
2
3 declare FORMAT=""
4 declare DEVICE=""
5 declare -i OLD_DD=0
6
7 # Binaires array for fusing
8 declare -a FUSING_BINARY_ARRAY
9 declare -i FUSING_BINARY_NUM=0
10
11 declare CONV_ASCII=""
12 declare -i FUS_ENTRY_NUM=0
13
14 # binary name | part number | bs | label | fs type
15 declare -a PART_TABLE=(
16         "boot.img"                      1       4M      boot                    vfat
17         "rootfs.img"                    2       4M      rootfs                  ext4
18         "system-data.img"               3       4M      system-data             ext4
19         "user.img"                      5       4M      user                    ext4
20         "modules.img"                   6       4M      modules                 ext4
21         "ramdisk.img"                   7       4M      ramdisk                 ext4
22         "ramdisk-recovery.img"          8       4M      ramdisk-recovery        ext4
23         "hal.img"                       10      4M      hal                     ext4
24         )
25
26 declare -r -i PART_TABLE_COL=5
27 declare -r -i PART_TABLE_ROW=${#PART_TABLE[*]}/${PART_TABLE_COL}
28
29 # partition table support
30 function get_index_use_name () {
31         local -r binary_name=$1
32
33         for ((idx=0;idx<$PART_TABLE_ROW;idx++)); do
34                 if [ ${PART_TABLE[idx * ${PART_TABLE_COL} + 0]} == "$binary_name" ]; then
35                         return $idx
36                 fi
37         done
38
39         # return out of bound index
40         return $idx
41 }
42
43 function print_message () {
44         local color=$1
45         local message=$2
46
47         tput setaf $color
48         tput bold
49         echo ""
50         echo $message
51         tput sgr 0
52 }
53
54 function check_ddversion () {
55         # NOTE
56         # before coreutils dd 8.24, dd doesn't support "status=progress"
57         # and the option causes fusing failure. For backward compatibility,
58         # do not use the option for old dd
59         local version=(`dd --version | head -1 | grep -o '[0-9]\+'`)
60         local major=${version[0]}
61         local minor=${version[1]}
62
63         if [ $major -lt 8 ];  then
64                 OLD_DD=1
65         elif [ $major -eq 8 -a $minor -lt 24 ];  then
66                 OLD_DD=1
67         fi
68 }
69
70 function fusing_image () {
71         local -r fusing_img=$1
72
73         # get binary info using basename
74         get_index_use_name $(basename "$fusing_img")
75         local -r -i part_idx=$?
76
77         if [ $part_idx -ne $PART_TABLE_ROW ];then
78                 local -r num=${PART_TABLE[${part_idx} * ${PART_TABLE_COL} + 1]}
79                 if [ "${num}" == "" ]; then
80                         local -r blktype=disk
81                 else
82                         local -r blktype=part
83                 fi
84                 local -r device=/dev/`lsblk ${DEVICE} -o TYPE,KNAME | grep ${blktype} | awk '{ print $2 }' | grep -G "[a-z]${num}\$"`
85                 local -r bs=${PART_TABLE[${part_idx} * ${PART_TABLE_COL} + 2]}
86         else
87                 echo "Not supported binary: $fusing_img"
88                 return
89         fi
90
91         local -r input_size=`du -b $fusing_img | awk '{print $1}'`
92         local -r input_size_mb=`expr $input_size / 1024 / 1024`
93
94         print_message 2 "[Fusing $1 ($input_size_mb MiB)]"
95         if [ "$blktype" == "part" ]; then
96                 local MOUNT_PART=`mount | grep $device`
97                 if [ "$MOUNT_PART" != "" ]; then
98                         umount $device
99                 fi
100         fi
101         if [ $OLD_DD == 1 ]; then
102                 dd if=$fusing_img | pv -s $input_size | dd of=$device bs=$bs
103         else
104                 dd if=$fusing_img of=$device bs=$bs status=progress oflag=direct
105         fi
106
107         local -r fstype=`blkid -o value -s TYPE $device`
108         if [[ "$fstype" =~ "ext" ]]; then
109                 resize2fs -f $device
110         fi
111 }
112
113 function fuse_image_tarball () {
114         local -r filepath=$1
115         local -r temp_dir="tar_tmp"
116
117         mkdir -p $temp_dir
118         tar xvf $filepath -C $temp_dir
119         cd $temp_dir
120
121         for file in *
122         do
123                 fusing_image $file
124         done
125
126         cd ..
127         rm -rf $temp_dir
128         eval sync
129 }
130
131 function fuse_image () {
132
133         if [ "$FUSING_BINARY_NUM" == 0 ]; then
134                 return
135         fi
136
137         for ((fuse_idx = 0 ; fuse_idx < $FUSING_BINARY_NUM ; fuse_idx++))
138         do
139                 local filename=${FUSING_BINARY_ARRAY[fuse_idx]}
140
141                 case "$filename" in
142                     *.tar | *.tar.gz)
143                         fuse_image_tarball $filename
144                         ;;
145                     *)
146                         fusing_image $filename
147                         ;;
148                 esac
149         done
150         echo ""
151 }
152
153 # partition format
154 function mkpart_3 () {
155         # NOTE: if your sfdisk version is less than 2.26.0, then you should use following sfdisk command:
156         # sfdisk --in-order --Linux --unit M $DISK <<-__EOF__
157
158         # NOTE: sfdisk 2.26 doesn't support units other than sectors and marks --unit option as deprecated.
159         # The input data needs to contain multipliers (MiB) instead.
160         local version=(`sfdisk -v | grep -o '[0-9]\+'`)
161         local major=${version[0]}
162         local minor=${version[1]}
163         local sfdisk_new=0
164         local support_delete=0
165
166         if [ $major -gt 2 ];  then
167                 sfdisk_new=1
168         else
169                 if [ $major -eq 2 -a $minor -ge 26 ];  then
170                         sfdisk_new=1
171                         if [ $major -eq 2 -a $minor -ge 28 ]; then
172                                 support_delete=1
173                         fi
174                 fi
175         fi
176
177         if [ $sfdisk_new == 0 ]; then
178                 echo "$(tput setaf 3)$(tput bold)NOTICE: Your sfidk ${version[0]}.${version[1]}  version is too old. It can do unstable behavior!"
179                 tput sgr 0
180                 echo ""
181
182         fi
183
184         local -r DISK=$DEVICE
185         local -r SIZE=`sfdisk -s $DISK`
186         local -r SIZE_MB=$((SIZE >> 10))
187
188         local -r BOOT_SZ=64
189         local -r ROOTFS_SZ=3072
190         local -r DATA_SZ=1344
191         local -r MODULE_SZ=32
192         local -r RAMDISK_SZ=32
193         local -r RAMDISK_RECOVERY_SZ=32
194         local -r INFORM_SZ=8
195         local -r HAL_SZ=256
196         local -r RESERVED2_SZ=125
197         local -r EXTEND_SZ=12
198
199         let "USER_SZ = $SIZE_MB - $BOOT_SZ - $ROOTFS_SZ - $DATA_SZ - $MODULE_SZ - $RAMDISK_SZ - $RAMDISK_RECOVERY_SZ - $INFORM_SZ - $EXTEND_SZ - $HAL_SZ - $RESERVED2_SZ"
200
201         local -r BOOT=${PART_TABLE[0 * ${PART_TABLE_COL} + 3]}
202         local -r ROOTFS=${PART_TABLE[1 * ${PART_TABLE_COL} + 3]}
203         local -r SYSTEMDATA=${PART_TABLE[2 * ${PART_TABLE_COL} + 3]}
204         local -r USER=${PART_TABLE[3 * ${PART_TABLE_COL} + 3]}
205         local -r MODULE=${PART_TABLE[4 * ${PART_TABLE_COL} + 3]}
206         local -r RAMDISK=${PART_TABLE[5 * ${PART_TABLE_COL} + 3]}
207         local -r RAMDISK_RECOVERY=${PART_TABLE[6 * ${PART_TABLE_COL} + 3]}
208         local -r INFORM=inform
209         local -r HAL=${PART_TABLE[7 * ${PART_TABLE_COL} + 3]}
210         local -r RESERVED2=reserved2
211
212         if [[ $USER_SZ -le 100 ]]
213         then
214                 echo "We recommend to use more than 4GB disk"
215                 exit 0
216         fi
217
218         echo "================================================"
219         echo "Label                     dev             size"
220         echo "================================================"
221         echo $BOOT"                     " $DISK"1       " $BOOT_SZ "MB"
222         echo $ROOTFS"                   " $DISK"2       " $ROOTFS_SZ "MB"
223         echo $SYSTEMDATA"               " $DISK"3       " $DATA_SZ "MB"
224         echo "[Extend]""                " $DISK"4"
225         echo " "$USER"                  " $DISK"5       " $USER_SZ "MB"
226         echo " "$MODULE"                " $DISK"6       " $MODULE_SZ "MB"
227         echo " "$RAMDISK"               " $DISK"7       " $RAMDISK_SZ "MB"
228         echo " "$RAMDISK_RECOVERY"      " $DISK"8       " $RAMDISK_RECOVERY_SZ "MB"
229         echo " "$INFORM"                        " $DISK"9       " $INFORM_SZ "MB"
230         echo " "$HAL"                   " $DISK"10      " $HAL_SZ "MB"
231         echo " "$RESERVED2"             " $DISK"11      " $RESERVED2_SZ "MB"
232
233         local MOUNT_LIST=`mount | grep $DISK | awk '{print $1}'`
234         for mnt in $MOUNT_LIST
235         do
236                 umount $mnt
237         done
238
239
240         if [ $sfdisk_new == 1 ]; then
241                 echo "Remove partition table..."
242                 if [ $support_delete == 1 ]; then
243                         sfdisk --delete $DISK
244                 else
245                         dd if=/dev/zero of=$DISK bs=512 count=16 conv=notrunc
246                 fi
247
248                 sfdisk $DISK <<-__EOF__
249                 4MiB,${BOOT_SZ}MiB,0xE,*
250                 8MiB,${ROOTFS_SZ}MiB,,-
251                 8MiB,${DATA_SZ}MiB,,-
252                 8MiB,,E,-
253                 ,${USER_SZ}MiB,,-
254                 ,${MODULE_SZ}MiB,,-
255                 ,${RAMDISK_SZ}MiB,,-
256                 ,${RAMDISK_RECOVERY_SZ}MiB,,-
257                 ,${INFORM_SZ}MiB,,-
258                 ,${HAL_SZ}MiB,,-
259                 ,${RESERVED2_SZ}MiB,,-
260                 __EOF__
261         else
262                 echo "Remove partition table..."
263                 dd if=/dev/zero of=$DISK bs=512 count=16 conv=notrunc
264
265                 # calculate start positions for alignment for extended partitions
266                 let "USER_START = 4 + $BOOT_SZ + $ROOTFS_SZ + $DATA_SZ + 1"
267                 let "MODULE_START = $USER_START + $USER_SZ + 1"
268                 let "RAMDISK_START = $MODULE_START + $MODULE_SZ + 1"
269                 let "RAMDISK_RECOVERY_START = $RAMDISK_START + $RAMDISK_SZ + 1"
270                 let "INFORM_START = $RAMDISK_RECOVERY_START + $RAMDISK_RECOVERY_SZ + 1"
271                 let "HAL_START = $INFORM_START + $INFORM_SZ + 1"
272                 let "RESERVED2_START = $HAL_START + $HAL_SZ + 1"
273
274                 sfdisk --in-order --Linux --unit M $DISK <<-__EOF__
275                 4,$BOOT_SZ,0xE,*
276                 ,$ROOTFS_SZ,,-
277                 ,$DATA_SZ,,-
278                 ,,E,-
279                 $USER_START,$USER_SZ,,-
280                 $MODULE_START,$MODULE_SZ,,-
281                 $RAMDISK_START,$RAMDISK_SZ,,-
282                 $RAMDISK_RECOVERY_START,$RAMDISK_RECOVERY_SZ,,-
283                 $INFORM_START,$INFORM_SZ,,-
284                 $HAL_START,$HAL_SZ,,-
285                 $RESERVED2_START,$RESERVED2_SZ,,-
286                 __EOF__
287         fi
288
289         for ((idx=0;idx<$PART_TABLE_ROW;idx++)); do
290                 local PART=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]${PART_TABLE[$idx * ${PART_TABLE_COL} + 1]}\$"`
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                 elif [ "${PART_TABLE[$idx * ${PART_TABLE_COL} + 4]}" == "ext4" ]; then
294                         mkfs.ext4 -q ${PART} -L ${PART_TABLE[$idx * ${PART_TABLE_COL} + 3]} -F
295                 else
296                         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]}"
297                 fi
298         done
299
300         local -r PART9=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]9\$"`
301         mkfs.ext4 -q ${PART9} -L $INFORM -F
302
303         # create "reboot-param.bin" file in inform partition for passing reboot parameter
304         # It should be done only once upon partition format.
305         mkdir mnt_tmp
306         mount -t ext4 ${PART9} ./mnt_tmp
307         touch ./mnt_tmp/reboot-param.bin
308         sync
309         umount ./mnt_tmp
310         rmdir mnt_tmp
311
312         local -r PART11=/dev/`lsblk ${DISK} -o TYPE,KNAME | grep part | awk '{ print $2 }' | grep -G "[a-z]11\$"`
313         mkfs.ext4 -q ${PART11} -L $RESERVED2 -F
314 }
315
316 function show_usage () {
317         echo "- Usage:"
318         echo "  sudo ./sd_fusing*.sh -d <device> [-b <path> <path> ..] [--format]"
319 }
320
321 function check_partition_format () {
322         if [ "$FORMAT" != "2" ]; then
323                 echo "-----------------------"
324                 echo "Skip $DEVICE format"
325                 echo "-----------------------"
326                 return 0
327         fi
328
329         echo "-------------------------------"
330         echo "Start $DEVICE format"
331         echo ""
332         mkpart_3
333         echo "End $DEVICE format"
334         echo "-------------------------------"
335         echo ""
336 }
337
338 function check_args () {
339         if [ "$DEVICE" == "" ]; then
340                 echo "$(tput setaf 1)$(tput bold)- Device node is empty!"
341                 show_usage
342                 tput sgr 0
343                 exit 0
344         fi
345
346         if [ "$DEVICE" != "" ]; then
347                 echo "Device: $DEVICE"
348         fi
349
350         if [ "$FUSING_BINARY_NUM" != 0 ]; then
351                 echo "Fusing binary: "
352                 for ((bid = 0 ; bid < $FUSING_BINARY_NUM ; bid++))
353                 do
354                         echo "  ${FUSING_BINARY_ARRAY[bid]}"
355                 done
356                 echo ""
357         fi
358
359         if [ "$FORMAT" == "1" ]; then
360                 echo ""
361                 echo "$(tput setaf 3)$(tput bold)$DEVICE will be formatted, Is it OK? [y/<n>]"
362                 tput sgr 0
363                 read input
364                 if [ "$input" == "y" ] || [ "$input" == "Y" ]; then
365                         FORMAT=2
366                 else
367                         FORMAT=0
368                 fi
369         fi
370 }
371
372 function check_device () {
373         if [ ! -b "$DEVICE" ]; then
374                 echo "No such device: $DEVICE"
375                 exit 0
376         fi
377
378         local REMOVABLE=`lsblk $DEVICE -nd -o RM | grep 1 | wc -l`
379         if [ "$REMOVABLE" == "0" ]; then
380                 echo ""
381                 echo "$(tput setaf 3)$(tput bold)$DEVICE is not a removable disk, Is it OK? [y/<n>]"
382                 tput sgr 0
383                 read input
384                 if [ "$input" != "y" ] && [ "$input" != "Y" ]; then
385                         exit 0
386                 fi
387         fi
388
389         if [ ! -w "$DEVICE" ]; then
390                 echo "Write not permitted: $DEVICE"
391                 exit 0
392         fi
393 }
394
395 function print_logo () {
396         echo ""
397         echo "Raspberry Pi downloader, version 2.1.1"
398         echo ""
399 }
400
401 print_logo
402
403 function add_fusing_binary() {
404         local declare binary_name=$1
405
406         if [ "$binary_name" != "" ]; then
407                 if [ -f "$binary_name" ]; then
408                         FUSING_BINARY_ARRAY[$FUSING_BINARY_NUM]=$binary_name
409
410                         FUSING_BINARY_NUM=$((FUSING_BINARY_NUM + 1))
411                 else
412                         echo "No such file: $binary_name"
413                 fi
414         fi
415 }
416
417
418 declare -i binary_option=0
419
420 while test $# -ne 0; do
421         option=$1
422         shift
423
424         case $option in
425         --f | --format)
426                 FORMAT="1"
427                 binary_option=0
428                 ;;
429         -d)
430                 DEVICE=$1
431                 binary_option=0
432                 shift
433                 ;;
434         -b)
435                 add_fusing_binary $1
436                 binary_option=1
437                 shift
438                 ;;
439         *)
440                 if [ $binary_option == 1 ];then
441                         add_fusing_binary $option
442                 else
443                         echo "Unkown command: $option"
444                         exit
445                 fi
446                 ;;
447         esac
448 done
449
450 check_args
451 check_device
452 check_partition_format
453 check_ddversion
454 fuse_image