Splitting out a first bunch of functions out to /live/live/boot/.
[live-boot-grml.git] / scripts / boot.sh
1 #!/bin/sh
2
3 # set -e
4
5 for _SCRIPT in /lib/live/boot/*
6 do
7         if [ -e "${_SCRIPT}" ]
8         then
9                 . ${_SCRIPT}
10         fi
11 done
12
13 export PATH="/root/usr/bin:/root/usr/sbin:/root/bin:/root/sbin:/usr/bin:/usr/sbin:/bin:/sbin"
14
15 echo "/root/lib" >> /etc/ld.so.conf
16 echo "/root/usr/lib" >> /etc/ld.so.conf
17
18 mountpoint="/live/image"
19 alt_mountpoint="/media"
20 LIVE_MEDIA_PATH="live"
21
22 HOSTNAME="host"
23
24 mkdir -p "${mountpoint}"
25 tried="/tmp/tried"
26
27 # Create /etc/mtab for debug purpose and future syncs
28 if [ ! -d /etc ]
29 then
30         mkdir /etc/
31 fi
32
33 if [ ! -f /etc/mtab ]
34 then
35         touch /etc/mtab
36 fi
37
38 . /scripts/live-helpers
39
40 if [ ! -f /live.vars ]
41 then
42         touch /live.vars
43 fi
44
45 is_live_path ()
46 {
47         DIRECTORY="${1}"
48
49         if [ -d "${DIRECTORY}"/"${LIVE_MEDIA_PATH}" ]
50         then
51                 for FILESYSTEM in squashfs ext2 ext3 ext4 xfs dir jffs2
52                 do
53                         if [ "$(echo ${DIRECTORY}/${LIVE_MEDIA_PATH}/*.${FILESYSTEM})" != "${DIRECTORY}/${LIVE_MEDIA_PATH}/*.${FILESYSTEM}" ]
54                         then
55                                 return 0
56                         fi
57                 done
58         fi
59
60         return 1
61 }
62
63 matches_uuid ()
64 {
65         if [ "${IGNORE_UUID}" ] || [ ! -e /conf/uuid.conf ]
66         then
67                 return 0
68         fi
69
70         path="${1}"
71         uuid="$(cat /conf/uuid.conf)"
72
73         for try_uuid_file in "${path}/.disk/live-uuid"*
74         do
75                 [ -e "${try_uuid_file}" ] || continue
76
77                 try_uuid="$(cat "${try_uuid_file}")"
78
79                 if [ "${uuid}" = "${try_uuid}" ]
80                 then
81                         return 0
82                 fi
83         done
84
85         return 1
86 }
87
88 get_backing_device ()
89 {
90         case "${1}" in
91                 *.squashfs|*.ext2|*.ext3|*.ext4|*.jffs2)
92                         echo $(setup_loop "${1}" "loop" "/sys/block/loop*" '0' "${LIVE_MEDIA_ENCRYPTION}" "${2}")
93                         ;;
94
95                 *.dir)
96                         echo "directory"
97                         ;;
98
99                 *)
100                         panic "Unrecognized live filesystem: ${1}"
101                         ;;
102         esac
103 }
104
105 match_files_in_dir ()
106 {
107         # Does any files match pattern ${1} ?
108         local pattern="${1}"
109
110         if [ "$(echo ${pattern})" != "${pattern}" ]
111         then
112                 return 0
113         fi
114
115         return 1
116 }
117
118 mount_images_in_directory ()
119 {
120         directory="${1}"
121         rootmnt="${2}"
122         mac="${3}"
123
124
125         if match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.squashfs" ||
126                 match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext2" ||
127                 match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext3" ||
128                 match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.ext4" ||
129                 match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.jffs2" ||
130                 match_files_in_dir "${directory}/${LIVE_MEDIA_PATH}/*.dir"
131         then
132                 [ -n "${mac}" ] && adddirectory="${directory}/${LIVE_MEDIA_PATH}/${mac}"
133                 setup_unionfs "${directory}/${LIVE_MEDIA_PATH}" "${rootmnt}" "${adddirectory}"
134         else
135                 panic "No supported filesystem images found at /${LIVE_MEDIA_PATH}."
136         fi
137 }
138
139 is_nice_device ()
140 {
141         sysfs_path="${1#/sys}"
142
143         if [ -e /lib/udev/path_id ]
144         then
145                 # squeeze
146                 PATH_ID="/lib/udev/path_id"
147         else
148                 # wheezy/sid (udev >= 174)
149                 PATH_ID="/sbin/udevadm test-builtin path_id"
150         fi
151
152         if ${PATH_ID} "${sysfs_path}" | egrep -q "ID_PATH=(usb|pci-[^-]*-(ide|sas|scsi|usb|virtio)|platform-sata_mv|platform-orion-ehci|platform-mmc|platform-mxsdhci)"
153         then
154                 return 0
155         elif echo "${sysfs_path}" | grep -q '^/block/vd[a-z]$'
156         then
157                 return 0
158         elif echo ${sysfs_path} | grep -q "^/block/dm-"
159         then
160                 return 0
161         elif echo ${sysfs_path} | grep -q "^/block/mtdblock"
162         then
163                 return 0
164         fi
165
166         return 1
167 }
168
169 check_dev ()
170 {
171         sysdev="${1}"
172         devname="${2}"
173         skip_uuid_check="${3}"
174
175         # support for fromiso=.../isofrom=....
176         if [ -n "$FROMISO" ]
177         then
178                 ISO_DEVICE=$(dirname $FROMISO)
179                 if ! [ -b $ISO_DEVICE ]
180                 then
181                         # to support unusual device names like /dev/cciss/c0d0p1
182                         # as well we have to identify the block device name, let's
183                         # do that for up to 15 levels
184                         i=15
185                         while [ -n "$ISO_DEVICE" ] && [ "$i" -gt 0 ]
186                         do
187                                 ISO_DEVICE=$(dirname ${ISO_DEVICE})
188                                 [ -b "$ISO_DEVICE" ] && break
189                                 i=$(($i -1))
190                         done
191                 fi
192
193                 if [ "$ISO_DEVICE" = "/" ]
194                 then
195                         echo "Warning: device for bootoption fromiso= ($FROMISO) not found.">>/boot.log
196                 else
197                         fs_type=$(get_fstype "${ISO_DEVICE}")
198                         if is_supported_fs ${fs_type}
199                         then
200                                 mkdir /live/fromiso
201                                 mount -t $fs_type "$ISO_DEVICE" /live/fromiso
202                                 ISO_NAME="$(echo $FROMISO | sed "s|$ISO_DEVICE||")"
203                                 loopdevname=$(setup_loop "/live/fromiso/${ISO_NAME}" "loop" "/sys/block/loop*" "" '')
204                                 devname="${loopdevname}"
205                         else
206                                 echo "Warning: unable to mount $ISO_DEVICE." >>/boot.log
207                         fi
208                 fi
209         fi
210
211         if [ -z "${devname}" ]
212         then
213                 devname=$(sys2dev "${sysdev}")
214         fi
215
216         if [ -d "${devname}" ]
217         then
218                 mount -o bind "${devname}" $mountpoint || continue
219
220                 if is_live_path $mountpoint
221                 then
222                         echo $mountpoint
223                         return 0
224                 else
225                         umount $mountpoint
226                 fi
227         fi
228
229         IFS=","
230         for device in ${devname}
231         do
232                 case "$device" in
233                         *mapper*)
234                                 # Adding lvm support
235                                 if [ -x /scripts/local-top/lvm2 ]
236                                 then
237                                         ROOT="$device" resume="" /scripts/local-top/lvm2
238                                 fi
239                                 ;;
240
241                         /dev/md*)
242                                 # Adding raid support
243                                 if [ -x /scripts/local-top/mdadm ]
244                                 then
245                                         cp /conf/conf.d/md /conf/conf.d/md.orig
246                                         echo "MD_DEVS=$device " >> /conf/conf.d/md
247                                         /scripts/local-top/mdadm
248                                         mv /conf/conf.d/md.orig /conf/conf.d/md
249                                 fi
250                                 ;;
251                 esac
252         done
253         unset IFS
254
255         [ -n "$device" ] && devname="$device"
256
257         [ -e "$devname" ] || continue
258
259         if [ -n "${LIVE_MEDIA_OFFSET}" ]
260         then
261                 loopdevname=$(setup_loop "${devname}" "loop" "/sys/block/loop*" "${LIVE_MEDIA_OFFSET}" '')
262                 devname="${loopdevname}"
263         fi
264
265         fstype=$(get_fstype "${devname}")
266
267         if is_supported_fs ${fstype}
268         then
269                 devuid=$(blkid -o value -s UUID "$devname")
270                 [ -n "$devuid" ] && grep -qs "\<$devuid\>" $tried && continue
271                 mount -t ${fstype} -o ro,noatime "${devname}" ${mountpoint} || continue
272                 [ -n "$devuid" ] && echo "$devuid" >> $tried
273
274                 if [ -n "${FINDISO}" ]
275                 then
276                         if [ -f ${mountpoint}/${FINDISO} ]
277                         then
278                                 umount ${mountpoint}
279                                 mkdir -p /live/findiso
280                                 mount -t ${fstype} -o ro,noatime "${devname}" /live/findiso
281                                 loopdevname=$(setup_loop "/live/findiso/${FINDISO}" "loop" "/sys/block/loop*" 0 "")
282                                 devname="${loopdevname}"
283                                 mount -t iso9660 -o ro,noatime "${devname}" ${mountpoint}
284                         else
285                                 umount ${mountpoint}
286                         fi
287                 fi
288
289                 if is_live_path ${mountpoint} && \
290                         ([ "${skip_uuid_check}" ] || matches_uuid ${mountpoint})
291                 then
292                         echo ${mountpoint}
293                         return 0
294                 else
295                         umount ${mountpoint} 2>/dev/null
296                 fi
297         fi
298
299         if [ -n "${LIVE_MEDIA_OFFSET}" ]
300         then
301                 losetup -d "${loopdevname}"
302         fi
303
304         return 1
305 }
306
307 find_livefs ()
308 {
309         timeout="${1}"
310
311         # don't start autodetection before timeout has expired
312         if [ -n "${LIVE_MEDIA_TIMEOUT}" ]
313         then
314                 if [ "${timeout}" -lt "${LIVE_MEDIA_TIMEOUT}" ]
315                 then
316                         return 1
317                 fi
318         fi
319
320         # first look at the one specified in the command line
321         case "${LIVE_MEDIA}" in
322                 removable-usb)
323                         for sysblock in $(removable_usb_dev "sys")
324                         do
325                                 for dev in $(subdevices "${sysblock}")
326                                 do
327                                         if check_dev "${dev}"
328                                         then
329                                                 return 0
330                                         fi
331                                 done
332                         done
333                         return 1
334                         ;;
335
336                 removable)
337                         for sysblock in $(removable_dev "sys")
338                         do
339                                 for dev in $(subdevices "${sysblock}")
340                                 do
341                                         if check_dev "${dev}"
342                                         then
343                                                 return 0
344                                         fi
345                                 done
346                         done
347                         return 1
348                         ;;
349
350                 *)
351                         if [ ! -z "${LIVE_MEDIA}" ]
352                         then
353                                 if check_dev "null" "${LIVE_MEDIA}" "skip_uuid_check"
354                                 then
355                                         return 0
356                                 fi
357                         fi
358                         ;;
359         esac
360
361         # or do the scan of block devices
362         # prefer removable devices over non-removable devices, so scan them first
363         devices_to_scan="$(removable_dev 'sys') $(non_removable_dev 'sys')"
364
365         for sysblock in $devices_to_scan
366         do
367                 devname=$(sys2dev "${sysblock}")
368                 [ -e "$devname" ] || continue
369                 fstype=$(get_fstype "${devname}")
370
371                 if /lib/udev/cdrom_id ${devname} > /dev/null
372                 then
373                         if check_dev "null" "${devname}"
374                         then
375                                 return 0
376                         fi
377                 elif is_nice_device "${sysblock}"
378                 then
379                         for dev in $(subdevices "${sysblock}")
380                         do
381                                 if check_dev "${dev}"
382                                 then
383                                         return 0
384                                 fi
385                         done
386                 elif [ "${fstype}" = "squashfs" -o \
387                         "${fstype}" = "btrfs" -o \
388                         "${fstype}" = "ext2" -o \
389                         "${fstype}" = "ext3" -o \
390                         "${fstype}" = "ext4" -o \
391                         "${fstype}" = "jffs2" ]
392                 then
393                         # This is an ugly hack situation, the block device has
394                         # an image directly on it.  It's hopefully
395                         # live-boot, so take it and run with it.
396                         ln -s "${devname}" "${devname}.${fstype}"
397                         echo "${devname}.${fstype}"
398                         return 0
399                 fi
400         done
401
402         return 1
403 }
404
405 integrity_check ()
406 {
407         media_mountpoint="${1}"
408
409         log_begin_msg "Checking media integrity"
410
411         cd ${media_mountpoint}
412         /bin/md5sum -c md5sum.txt < /dev/tty8 > /dev/tty8
413         RC="${?}"
414
415         log_end_msg
416
417         if [ "${RC}" -eq 0 ]
418         then
419                 log_success_msg "Everything ok, will reboot in 10 seconds."
420                 sleep 10
421                 cd /
422                 umount ${media_mountpoint}
423                 sync
424                 echo u > /proc/sysrq-trigger
425                 echo b > /proc/sysrq-trigger
426         else
427                 panic "Not ok, a media defect is likely, switch to VT8 for details."
428         fi
429 }
430
431 mountroot ()
432 {
433         if [ -x /scripts/local-top/cryptroot ]; then
434             /scripts/local-top/cryptroot
435         fi
436
437         exec 6>&1
438         exec 7>&2
439         exec > boot.log
440         exec 2>&1
441         tail -f boot.log >&7 &
442         tailpid="${!}"
443
444         # Ensure 'panic' function is overridden
445         . /scripts/live-functions
446
447         Arguments
448
449         maybe_break live-premount
450         log_begin_msg "Running /scripts/live-premount"
451         run_scripts /scripts/live-premount
452         log_end_msg
453
454         # Needed here too because some things (*cough* udev *cough*)
455         # changes the timeout
456
457         if [ ! -z "${NETBOOT}" ] || [ ! -z "${FETCH}" ] || [ ! -z "${HTTPFS}" ] || [ ! -z "${FTPFS}" ]
458         then
459                 if do_netmount
460                 then
461                         livefs_root="${mountpoint}"
462                 else
463                         panic "Unable to find a live file system on the network"
464                 fi
465         else
466                 if [ -n "${ISCSI_PORTAL}" ]
467                 then
468                         do_iscsi && livefs_root="${mountpoint}"
469                 elif [ -n "${PLAIN_ROOT}" ] && [ -n "${ROOT}" ]
470                 then
471                         # Do a local boot from hd
472                         livefs_root=${ROOT}
473                 else
474                         if [ -x /usr/bin/memdiskfind ]
475                         then
476                                 MEMDISK=$(/usr/bin/memdiskfind)
477
478                                 if [ $? -eq 0 ]
479                                 then
480                                         # We found a memdisk, set up phram
481                                         modprobe phram phram=memdisk,${MEMDISK}
482
483                                         # Load mtdblock, the memdisk will be /dev/mtdblock0
484                                         modprobe mtdblock
485                                 fi
486                         fi
487
488                         # Scan local devices for the image
489                         i=0
490                         while [ "$i" -lt 60 ]
491                         do
492                                 livefs_root=$(find_livefs ${i})
493
494                                 if [ -n "${livefs_root}" ]
495                                 then
496                                         break
497                                 fi
498
499                                 sleep 1
500                                 i="$(($i + 1))"
501                         done
502                 fi
503         fi
504
505         if [ -z "${livefs_root}" ]
506         then
507                 panic "Unable to find a medium containing a live file system"
508         fi
509
510         if [ "${INTEGRITY_CHECK}" ]
511         then
512                 integrity_check "${livefs_root}"
513         fi
514
515         if [ "${TORAM}" ]
516         then
517                 live_dest="ram"
518         elif [ "${TODISK}" ]
519         then
520                 live_dest="${TODISK}"
521         fi
522
523         if [ "${live_dest}" ]
524         then
525                 log_begin_msg "Copying live media to ${live_dest}"
526                 copy_live_to "${livefs_root}" "${live_dest}"
527                 log_end_msg
528         fi
529
530         # if we do not unmount the ISO we can't run "fsck /dev/ice" later on
531         # because the mountpoint is left behind in /proc/mounts, so let's get
532         # rid of it when running from RAM
533         if [ -n "$FROMISO" ] && [ "${TORAM}" ]
534         then
535                 losetup -d /dev/loop0
536
537                 if is_mountpoint /live/fromiso
538                 then
539                         umount /live/fromiso
540                         rmdir --ignore-fail-on-non-empty /live/fromiso \
541                                 >/dev/null 2>&1 || true
542                 fi
543         fi
544
545         if [ -n "${MODULETORAMFILE}" ] || [ -n "${PLAIN_ROOT}" ]
546         then
547                 setup_unionfs "${livefs_root}" "${rootmnt}"
548         else
549                 mac="$(get_mac)"
550                 mac="$(echo ${mac} | sed 's/-//g')"
551                 mount_images_in_directory "${livefs_root}" "${rootmnt}" "${mac}"
552         fi
553
554
555         if [ -n "${ROOT_PID}" ] ; then
556                 echo "${ROOT_PID}" > "${rootmnt}"/live/root.pid
557         fi
558
559         log_end_msg
560
561         # unionfs-fuse needs /dev to be bind-mounted for the duration of
562         # live-bottom; udev's init script will take care of things after that
563         if [ "${UNIONTYPE}" = unionfs-fuse ]
564         then
565                 mount -n -o bind /dev "${rootmnt}/dev"
566         fi
567
568         # Move to the new root filesystem so that programs there can get at it.
569         if [ ! -d /root/live/image ]
570         then
571                 mkdir -p /root/live/image
572                 mount --move /live/image /root/live/image
573         fi
574
575         # aufs2 in kernel versions around 2.6.33 has a regression:
576         # directories can't be accessed when read for the first the time,
577         # causing a failure for example when accessing /var/lib/fai
578         # when booting FAI, this simple workaround solves it
579         ls /root/* >/dev/null 2>&1
580
581         # Move findiso directory to the new root filesystem so that programs there can get at it.
582         if [ -d /live/findiso ] && [ ! -d /root/live/findiso ]
583         then
584                 mkdir -p /root/live/findiso
585                 mount -n --move /live/findiso /root/live/findiso
586         fi
587
588         # if we do not unmount the ISO we can't run "fsck /dev/ice" later on
589         # because the mountpoint is left behind in /proc/mounts, so let's get
590         # rid of it when running from RAM
591         if [ -n "$FINDISO" ] && [ "${TORAM}" ]
592         then
593                 losetup -d /dev/loop0
594
595                 if is_mountpoint /root/live/findiso
596                 then
597                         umount /root/live/findiso
598                         rmdir --ignore-fail-on-non-empty /root/live/findiso \
599                                 >/dev/null 2>&1 || true
600                 fi
601         fi
602
603         # copy snapshot configuration if exists
604         if [ -f snapshot.conf ]
605         then
606                 log_begin_msg "Copying snapshot.conf to ${rootmnt}/etc/live/boot.d"
607                 if [ ! -d "${rootmnt}/etc/live/boot.d" ]
608                 then
609                         mkdir -p "${rootmnt}/etc/live/boot.d"
610                 fi
611                 cp snapshot.conf "${rootmnt}/etc/live/boot.d/"
612                 log_end_msg
613         fi
614
615         if [ -f /etc/resolv.conf ] && [ ! -s ${rootmnt}/etc/resolv.conf ]
616         then
617                 log_begin_msg "Copying /etc/resolv.conf to ${rootmnt}/etc/resolv.conf"
618                 cp -v /etc/resolv.conf ${rootmnt}/etc/resolv.conf
619                 log_end_msg
620         fi
621
622         maybe_break live-bottom
623         log_begin_msg "Running /scripts/live-bottom\n"
624
625         run_scripts /scripts/live-bottom
626         log_end_msg
627
628         if [ "${UNIONFS}" = unionfs-fuse ]
629         then
630                 umount "${rootmnt}/dev"
631         fi
632
633         exec 1>&6 6>&-
634         exec 2>&7 7>&-
635         kill ${tailpid}
636         [ -w "${rootmnt}/var/log/" ] && mkdir -p /var/log/live && cp boot.log "${rootmnt}/var/log/live" 2>/dev/null
637 }