5434a0cb659d7e5d34bd330a5027074d664367e3
[platform/upstream/system-installer.git] / scripts / system-installer
1 #!/bin/sh
2
3 AUTOMODE=
4 PLYMOUTH=
5 REBOOT_ON_FAILURE=
6
7 while getopts ":a" opt; do
8   case $opt in
9     a)
10     AUTOMODE=1
11       ;;
12     \?)
13       echo "Invalid option: -$OPTARG" >&2
14       ;;
15   esac
16 done
17
18 if [ -z "$AUTOMODE" ]; then
19     PLYMOUTH=0
20     REBOOT_ON_FAILURE=0
21 else
22     PLYMOUTH=1
23     REBOOT_ON_FAILURE=1
24 fi
25
26 function message {
27     if [ -n "$PLYMOUTH" -a "$PLYMOUTH" -eq 1 ]; then
28         plymouth display-message  --text "$1"
29     else
30         echo $1
31     fi
32 }
33
34 function check_echo_reboot {
35        read key
36        if [[ $key != 'r' && $key != 'R' ]]; then
37                check_echo_reboot
38        fi
39 }
40
41 function read_config {
42     local CONF_FILE=""
43     CONF_FILE="/etc/installer.conf"
44
45     if [ ! -e $CONF_FILE ]; then
46         message "Installation failure, missing /etc/installer.conf"
47         test $REBOOT_ON_FAILURE -eq 1 &&  (
48             sleep 5
49             /usr/sbin/reboot
50         )
51         exit 1
52     else
53         . $CONF_FILE
54     fi
55 }
56
57 function set_mounts {
58     SRCMNT=$(mktemp -d /media/srctmp.XXXXXX)
59     TGTMNT=$(mktemp -d /media/tgttmp.XXXXXX)
60     SRCOSMNT=$(mktemp -d /media/srcostmp.XXXXXX)
61 }
62
63 function find_devices {
64     for i in $(ls /sys/block/*/device/model); do
65         dev=$(echo $i | cut -d'/' -f-4) ;
66         device=$(echo $i | cut -d'/' -f4)
67         grep -q 1 $dev/removable
68         if [ "$?" = "1" ]; then
69             TARGET_DEV="/dev/$device";
70             break
71         fi
72     done
73
74     if [ -z "$TARGET_DEV" ]; then
75         message "Installation failure, unable to find suitable install target media"
76         test $REBOOT_ON_FAILURE -eq 1 &&  (
77             sleep 5
78             /usr/sbin/reboot
79         )
80         exit 1
81     fi
82 }
83
84 # Global variable for storing the partition option parameters;
85 params=
86
87 function msdos_partition_options {
88     # the partition number
89     local i=$1
90     # used for storing the per-part variables,
91     # accessed via indirect referencing
92     local tmp=""
93
94     tmp="INSTALLERFW_PART${i}_SIZE"
95     local size=${!tmp}
96     [ -z "$size" ] && size="1024"
97     if [[ "$INSTALLERFW_PART_COUNT" = "$((i+1))" ]]; then
98         # an 'empty' value means that sfdisk will use
99         # the defaults, in this case expanding to the
100         # end of the disk
101         size=""
102     fi
103     params=$(printf "${params}\n%s" ",${size}")
104
105     tmp="INSTALLERFW_PART${i}_FSTYPE"
106     local fstype=${!tmp}
107     local typeid='83'
108     [ "$fstype" = "swap" ] && typeid='82'
109     params=$(printf "${params}%s" ",${typeid}")
110
111     # handle bootflag last
112     tmp="INSTALLERFW_PART${i}_BOOTFLAG"
113     local bootflag=${!tmp}
114     if [ "$bootflag" = "True" ]; then
115         params=$(printf "${params}%s" ',*')
116     else
117         params=$(printf "${params}\n")
118     fi
119 }
120
121 function gpt_partition_options {
122     # the partition number
123     local i=$1
124     # used for storing the per-part variables,
125     # accessed via indirect referencing
126     local tmp=""
127
128     tmp="INSTALLERFW_PART${i}_ALIGN"
129     local align=${!tmp}
130     [ -n "$align" ] && params=$(printf "${params}%s" " --set-alignment=${align}")
131
132     # sgdisk uses '0' to mean 'default value'
133     params=$(printf "$params%s" " --new=0:0")
134
135     tmp="INSTALLERFW_PART${i}_SIZE"
136     local size=${!tmp}
137     if [[ "$INSTALLERFW_PART_COUNT" = "$((i+1))" ]]; then
138         size="0"
139     fi
140     [ -z "$size" ] && size="1024"
141     [ -n "$size" ] && params=$(printf "${params}%s" ":${size}M")
142
143     # TODO: need to handle swap partition types if encountered
144
145     # the following GUID option does not accept default partition values,
146     # so partition numbering must start at index 1, not 0
147     local partnum="$((i+1))"
148
149     tmp="INSTALLERFW_PART${i}_TYPE_ID"
150     local typeid=${!tmp}
151     [ -n "$typeid" ] && params=$(printf "${params}%s" " --typecode=${partnum}:${typeid}")
152 }
153
154 function partition_msdos {
155     # make sure there is a newline in the heredoc,
156     # or else sfdisk fails to parse the input
157     /usr/sbin/sfdisk --in-order -uM ${TARGET_DEV} << EOF
158 ${1}
159
160 EOF
161     sync
162 }
163
164 function partition_gpt {
165     /usr/sbin/sgdisk -Z ${TARGET_DEV}
166     /usr/sbin/sgdisk ${1} ${TARGET_DEV}
167     sync
168 }
169
170 function format_device {
171     local fstype=$1
172     local instfw_pnum=$2
173     # the actual partition numbers begin at index 1, not 0
174     local partnum="$((instfw_pnum+1))"
175
176     # TODO: need to handle swap partitions
177
178     /usr/sbin/mkfs.${fstype} ${TARGET_DEV}${partnum}
179
180     if [[ ${fstype} = "btrfs" ]]; then
181         mount ${TARGET_DEV}${partnum} $TGTMNT
182         /usr/sbin/btrfs subvolume create ${TGTMNT}/tizen
183         /usr/sbin/btrfs subvolume create ${TGTMNT}/tizen/.snapshots
184         SUBVOLID=$(/usr/sbin/btrfs subvolume list $TGTMNT | grep 'tizen$' | awk '{ print $2 }')
185         echo "Setting subvolume ${SUBVOLID} as default"
186         /usr/sbin/btrfs subvolume set-default $SUBVOLID $TGTMNT
187         sync
188         umount $TGTMNT
189     fi
190 }
191
192 function mount_device {
193     local mountpoint=$1
194     local instfw_pnum=$2
195     # the actual partition numbers begin at index 1, not 0
196     local partnum="$((instfw_pnum+1))"
197
198     SRCOSMNT="/"
199
200     # we make this substitution in extlinux.conf on the target device
201     [ "$mountpoint" = "/" ] && ROOTFS="${TARGET_DEV}${partnum}"
202
203     mkdir -p ${TGTMNT}/${mountpoint}
204
205     # for this to work, the rootfs partition entry in installer.conf
206     # must be first entry, or else some mount points will be hidden
207     # during the rsync
208     mount ${TARGET_DEV}${partnum} ${TGTMNT}/${mountpoint}
209 }
210
211 function install_extlinux {
212     mkdir -p ${TGTMNT}/boot/extlinux
213     cat > ${TGTMNT}/boot/extlinux/extlinux.conf << EOF
214 default vesamenu.c32
215 timeout 10
216
217 menu background splash.png
218 menu title Welcome to Tizen PC!
219 menu color border 0 #ffffffff #00000000
220 menu color sel 7 #ff000000 #ffffffff
221 menu color title 0 #ffffffff #00000000
222 menu color tabmsg 0 #ffffffff #00000000
223 menu color unsel 0 #ffffffff #00000000
224 menu color hotsel 0 #ff000000 #ffffffff
225 menu color hotkey 7 #ffffffff #ff000000
226 menu color timeout_msg 0 #ffffffff #00000000
227 menu color timeout 0 #ffffffff #00000000
228 menu color cmdline 0 #ffffffff #00000000
229 menu hidden
230 menu clear
231 label tizen
232   menu label Boot Tizen
233   kernel ../vmlinuz
234   append root=${ROOTFS} ${INSTALLERFW_KERNEL_OPTS} ${ROOTFLAGS}
235 menu default
236 EOF
237
238     cp /usr/share/branding/default/syslinux/syslinux-vesa-splash.jpg ${TGTMNT}/boot/extlinux/splash.png
239
240     cat /usr/share/syslinux/mbr.bin > ${TARGET_DEV}
241     /sbin/extlinux -i  ${TGTMNT}/boot/extlinux
242 }
243
244 function install_os {
245     rsync  -WaHXSh --exclude='/dev/' --exclude='/lost+found/' --exclude='/media/*' --exclude='/sys/' --exclude='/proc/' --exclude="/tmp/" --exclude="/run/"  $SRCOSMNT/ $TGTMNT
246
247     mkdir ${TGTMNT}/dev/
248     chmod 0755 ${TGTMNT}/dev
249
250     # TODO: switch to using systemd mount units instead of the fstab
251     #rm ${TGTMNT}/etc/fstab
252
253     if [[ $FILESYSTEM = "btrfs" ]]; then
254         ROOTFLAGS="rootflags=subvol=tizen"
255     else
256         ROOTFLAGS=""
257     fi
258
259     if [ "$INSTALLERFW_PTABLE_FORMAT" = "msdos" ]; then
260         install_extlinux
261     fi
262
263     if [[ $FILESYSTEM = "btrfs" ]]; then
264         sed -i 's|SUBVOLUME="/"|SUBVOLUME="'${TGTMNT}'"|' /etc/snapper/configs/root
265         snapper create -d "Factory Default"
266     fi
267 }
268
269 function unmount_devices {
270     sync
271     sleep 2
272     [ -d "$TGTMNT" ] && umount -R $TGTMNT
273 }
274
275 message "This installation will wipe all data from the hard drive, hit Y key to continue or ctrl-alt-del to abort."
276 if [ -n "$PLYMOUTH" -a "$PLYMOUTH" -eq 1 ]; then
277     plymouth watch-keystroke --command="/usr/bin/test" --keys "yY"
278 else
279     read key
280     if [[ $key != 'y' && $key != 'Y' ]]; then
281         test $REBOOT_ON_FAILURE -eq 1 && /usr/sbin/reboot
282     fi
283 fi
284 if [ -n "$PLYMOUTH" -a "$PLYMOUTH" -eq 1 ]; then
285     plymouth hide-message  --text "This installation will wipe all data from the hard drive, hit Y key to continue or ctrl-alt-del to abort."
286 fi
287
288 read_config
289 set_mounts
290 find_devices
291 message "Installing on to the hard disk now, this will take a few minutes..."
292
293 pnum=0
294 # first, generate the option list to pass to either 'sfdisk' or 'sgdisk'
295 while [ "$pnum" -lt "$INSTALLERFW_PART_COUNT" ]; do
296     if [ "$INSTALLERFW_PTABLE_FORMAT" = "msdos" ]; then
297         msdos_partition_options $pnum
298     elif [ "$INSTALLERFW_PTABLE_FORMAT" = "gpt" ]; then
299         gpt_partition_options $pnum
300     fi
301     pnum="$((pnum+1))"
302 done
303
304 # now, do the partitioning
305 if [ "$INSTALLERFW_PTABLE_FORMAT" = "msdos" ]; then
306     partition_msdos "$params"
307 elif [ "$INSTALLERFW_PTABLE_FORMAT" = "gpt" ]; then
308     partition_gpt "$params"
309 fi
310
311 pnum="$((INSTALLERFW_PART_COUNT-1))"
312 # NOTE: for now, partitions are processed in reverse order, and we
313 # expect the rootfs to be the last entry in installer.conf
314 while [ "$pnum" -ge "0" ]; do
315     tmp="INSTALLERFW_PART${pnum}_FSTYPE"
316     fstype=${!tmp}
317
318     format_device $fstype $pnum
319
320     tmp="INSTALLERFW_PART${pnum}_MOUNTPOINT"
321     mountpoint=${!tmp}
322
323     mount_device $mountpoint $pnum
324
325     pnum="$((pnum-1))"
326 done
327
328 unset fstype
329 unset mountpoint
330
331 install_os
332 unmount_devices
333
334 if [ -n "$PLYMOUTH"  -a "$PLYMOUTH" -eq 1 ]; then
335     plymouth hide-message  --text "Installing on to the hard disk now, this will take a few minutes..."
336 fi
337 message "Hit R key to reboot and then remove the usb stick. Enjoy!"
338
339 if [ -n "$PLYMOUTH" -a "$PLYMOUTH" -eq 1 ]; then
340     plymouth watch-keystroke --command="/usr/bin/test" --keys "rR"
341 else
342     check_echo_reboot
343 fi
344 /usr/sbin/reboot