]>
Commit | Line | Data |
---|---|---|
7f64a3fe | 1 | #!/bin/sh |
cc02093d HH |
2 | # -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- |
3 | # ex: ts=8 sw=4 sts=4 et filetype=sh | |
a5e56335 JK |
4 | # |
5 | # Licensed under the GPLv2 | |
6 | # | |
cc02093d | 7 | # Copyright 2008-2010, Red Hat, Inc. |
ac36d5db | 8 | # Harald Hoyer <harald@redhat.com> |
a5e56335 | 9 | # Jeremy Katz <katzj@redhat.com> |
ec9315e5 | 10 | |
ac36d5db HH |
11 | wait_for_loginit() |
12 | { | |
8f5d3689 HH |
13 | set +x |
14 | [ "$RD_DEBUG" = "yes" ] || return | |
7eb40c48 | 15 | [ -e /run/initramfs/loginit.pipe ] || return |
8f5d3689 HH |
16 | echo "DRACUT_LOG_END" |
17 | exec 0<>/dev/console 1<>/dev/console 2<>/dev/console | |
cc02093d | 18 | # wait for loginit |
8f5d3689 | 19 | i=0 |
3b403b32 | 20 | while [ $i -lt 10 ]; do |
7eb40c48 | 21 | if [ ! -e /run/initramfs/loginit.pipe ]; then |
8f5d3689 HH |
22 | j=$(jobs) |
23 | [ -z "$j" ] && break | |
24 | [ -z "${j##*Running*}" ] || break | |
25 | fi | |
26 | sleep 0.1 | |
27 | i=$(($i+1)) | |
3b403b32 | 28 | done |
ac36d5db | 29 | |
8f5d3689 HH |
30 | if [ $i -eq 10 ]; then |
31 | kill %1 >/dev/null 2>&1 | |
7eb40c48 | 32 | kill $(while read line;do echo $line;done</run/initramfs/loginit.pid) |
ac36d5db | 33 | fi |
8f5d3689 HH |
34 | |
35 | set -x | |
7eb40c48 | 36 | rm -f /run/initramfs/loginit.pipe /run/initramfs/loginit.pid |
ac36d5db HH |
37 | } |
38 | ||
ec9315e5 JK |
39 | emergency_shell() |
40 | { | |
a382492b | 41 | set +e |
5db587d7 | 42 | if [ "$1" = "-n" ]; then |
b5664d5d | 43 | _rdshell_name=$2 |
3b403b32 | 44 | shift 2 |
b5664d5d LB |
45 | else |
46 | _rdshell_name=dracut | |
47 | fi | |
a3a3448d | 48 | echo ; echo |
a382492b | 49 | warn $@ |
0b53ca70 | 50 | source_hook emergency |
81f83dab | 51 | echo |
a382492b | 52 | wait_for_loginit |
03f405bc | 53 | [ -e /run/initramfs/.die ] && exit 1 |
9b793450 | 54 | if getargbool 1 rd.shell -y rdshell || getarg rd.break rdbreak; then |
81f83dab | 55 | echo "Dropping to debug shell." |
a3a3448d | 56 | echo |
b5664d5d LB |
57 | export PS1="$_rdshell_name:\${PWD}# " |
58 | [ -e /.profile ] || echo "exec 0<>/dev/console 1<>/dev/console 2<>/dev/console" > /.profile | |
59 | sh -i -l | |
a3a3448d | 60 | else |
a382492b HH |
61 | warn "Boot has failed. To debug this issue add \"rdshell\" to the kernel command line." |
62 | # cause a kernel panic | |
63 | exit 1 | |
a3a3448d | 64 | fi |
ec9315e5 | 65 | } |
ec9315e5 | 66 | |
bb040f93 HH |
67 | NEWROOT="/sysroot" |
68 | ||
a75c29be | 69 | trap "emergency_shell Signal caught!" 0 |
182660d8 HH |
70 | OLDPATH=$PATH |
71 | PATH=/usr/sbin:/usr/bin:/sbin:/bin | |
72 | export PATH | |
a890fe29 | 73 | |
36e30eb0 | 74 | RD_DEBUG="" |
b8f39ef1 | 75 | . /lib/dracut-lib.sh |
df44688f | 76 | |
5e1898fa | 77 | [ -c /dev/null ] || mknod -m 0666 /dev/null c 1 3 |
a890fe29 | 78 | |
ec9315e5 | 79 | # mount some important things |
a6c34848 HH |
80 | [ ! -d /proc/self ] && \ |
81 | mount -t proc -o nosuid,noexec,nodev /proc /proc >/dev/null 2>&1 | |
82 | ||
83 | [ ! -d /sys/kernel ] && \ | |
84 | mount -t sysfs -o nosuid,noexec,nodev /sys /sys >/dev/null 2>&1 | |
85 | ||
86 | setdebug | |
87 | ||
88 | if [ "$RD_DEBUG" = "yes" ]; then | |
89 | getarg quiet && DRACUT_QUIET="yes" | |
90 | a=$(getarg loglevel=) | |
91 | [ -n "$a" ] && [ $a -ge 8 ] && unset DRACUT_QUIET | |
92 | fi | |
a890fe29 | 93 | |
b2415f44 HH |
94 | if [ -x /lib/systemd/systemd-timestamp ]; then |
95 | RD_TIMESTAMP=$(/lib/systemd/systemd-timestamp) | |
96 | else | |
97 | read RD_TIMESTAMP _tmp < /proc/uptime | |
98 | unset _tmp | |
99 | fi | |
647bef8c | 100 | |
336eb5b0 | 101 | ismounted /sys || \ |
dbad9f46 HH |
102 | mount -t sysfs -o nosuid,noexec,nodev /sys /sys >/dev/null 2>&1 |
103 | ||
104 | if ! ismounted /dev; then | |
e0364f95 | 105 | # try to mount devtmpfs |
44110df2 | 106 | if ! mount -t devtmpfs -o mode=0755,nosuid,noexec udev /dev >/dev/null 2>&1; then |
e0364f95 | 107 | # if it failed fall back to normal tmpfs |
3b403b32 | 108 | mount -t tmpfs -o mode=0755,nosuid udev /dev >/dev/null 2>&1 |
cc02093d HH |
109 | # Make some basic devices first, let udev handle the rest |
110 | mknod -m 0666 /dev/null c 1 3 | |
111 | mknod -m 0666 /dev/ptmx c 5 2 | |
112 | mknod -m 0600 /dev/console c 5 1 | |
113 | mknod -m 0660 /dev/kmsg c 1 11 | |
3473f5d9 HH |
114 | fi |
115 | fi | |
d0e2110a | 116 | |
4af673c3 | 117 | # prepare the /dev directory |
dbad9f46 HH |
118 | [ ! -h /dev/fd ] && ln -s /proc/self/fd /dev/fd >/dev/null 2>&1 |
119 | [ ! -h /dev/stdin ] && ln -s /proc/self/fd/0 /dev/stdin >/dev/null 2>&1 | |
120 | [ ! -h /dev/stdout ] && ln -s /proc/self/fd/1 /dev/stdout >/dev/null 2>&1 | |
121 | [ ! -h /dev/stderr ] && ln -s /proc/self/fd/2 /dev/stderr >/dev/null 2>&1 | |
122 | ||
123 | if ! ismounted /dev/pts; then | |
124 | mkdir -m 0755 /dev/pts | |
125 | mount -t devpts -o gid=5,mode=620,noexec,nosuid devpts /dev/pts >/dev/null 2>&1 | |
126 | fi | |
127 | ||
128 | if ! ismounted /dev/shm; then | |
129 | mkdir -m 0755 /dev/shm | |
130 | mount -t tmpfs -o mode=1777,nosuid,nodev tmpfs /dev/shm >/dev/null 2>&1 | |
131 | fi | |
132 | ||
133 | if ! ismounted /run; then | |
134 | mkdir -m 0755 /newrun | |
135 | mount -t tmpfs -o mode=0755,nosuid,nodev tmpfs /newrun >/dev/null 2>&1 | |
136 | cp -a -t /newrun /run/* | |
137 | mount --move /newrun /run | |
138 | rm -fr /newrun | |
139 | fi | |
77e607a3 HH |
140 | |
141 | UDEVVERSION=$(udevadm --version) | |
0afae1c7 | 142 | if [ $UDEVVERSION -gt 166 ]; then |
19f3a804 | 143 | # newer versions of udev use /run/udev/rules.d |
19f3a804 | 144 | export UDEVRULESD=/run/udev/rules.d |
77e607a3 | 145 | else |
3b403b32 | 146 | mkdir -m 0755 /dev/.udev /dev/.udev/rules.d |
77e607a3 HH |
147 | export UDEVRULESD=/dev/.udev/rules.d |
148 | fi | |
149 | ||
a6c34848 | 150 | if [ "$RD_DEBUG" = "yes" ]; then |
7eb40c48 HH |
151 | mkfifo /run/initramfs/loginit.pipe |
152 | loginit $DRACUT_QUIET </run/initramfs/loginit.pipe >/dev/console 2>&1 & | |
153 | exec >/run/initramfs/loginit.pipe 2>&1 | |
ac36d5db HH |
154 | else |
155 | exec 0<>/dev/console 1<>/dev/console 2<>/dev/console | |
4592b698 | 156 | fi |
ac36d5db | 157 | |
0375106c HH |
158 | source_conf /etc/conf.d |
159 | ||
e4502814 | 160 | # run scriptlets to parse the command line |
fa7ada31 | 161 | getarg 'rd.break=cmdline' 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline" |
0b53ca70 | 162 | source_hook cmdline |
e4502814 | 163 | |
0fd1ab9d PS |
164 | [ -z "$root" ] && die "No or empty root= argument" |
165 | [ -z "$rootok" ] && die "Don't know how to handle 'root=$root'" | |
d15c7a1a | 166 | |
7d7efa4a DD |
167 | # Network root scripts may need updated root= options, |
168 | # so deposit them where they can see them (udev purges the env) | |
169 | { | |
170 | echo "root='$root'" | |
171 | echo "rflags='$rflags'" | |
172 | echo "fstype='$fstype'" | |
2734a875 | 173 | echo "netroot='$netroot'" |
7d7efa4a DD |
174 | echo "NEWROOT='$NEWROOT'" |
175 | } > /tmp/root.info | |
176 | ||
a08c1f45 | 177 | # pre-udev scripts run before udev starts, and are run only once. |
fa7ada31 | 178 | getarg 'rd.break=pre-udev' 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break before pre-udev" |
0b53ca70 | 179 | source_hook pre-udev |
ec1ad334 | 180 | |
ec9315e5 | 181 | # start up udev and trigger cold plugs |
0e0031dc | 182 | udevd --daemon --resolve-names=never |
2a652c0b HH |
183 | |
184 | UDEV_LOG_PRIO_ARG=--log-priority | |
185 | UDEV_QUEUE_EMPTY="udevadm settle --timeout=0" | |
186 | ||
187 | if [ $UDEVVERSION -lt 140 ]; then | |
cc02093d HH |
188 | UDEV_LOG_PRIO_ARG=--log_priority |
189 | UDEV_QUEUE_EMPTY="udevadm settle --timeout=1" | |
2a652c0b HH |
190 | fi |
191 | ||
2a9b7039 HH |
192 | getargbool 0 rd.udev.info -y rdudevinfo && udevproperty "$UDEV_LOG_PRIO_ARG=info" |
193 | getargbool 0 rd.udev.debug -y rdudevdebug && udevproperty "$UDEV_LOG_PRIO_ARG=debug" | |
194 | udevproperty "hookdir=$hookdir" | |
1eeddd31 | 195 | |
fa7ada31 | 196 | getarg 'rd.break=pre-trigger' 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break before pre-trigger" |
0b53ca70 | 197 | source_hook pre-trigger |
1eeddd31 HH |
198 | |
199 | # then the rest | |
cd83e4c5 | 200 | udevadm trigger --action=add $udevtriggeropts >/dev/null 2>&1 |
eab677a2 | 201 | |
fa7ada31 | 202 | getarg 'rd.break=initqueue' 'rdbreak=initqueue' && emergency_shell -n initqueue "Break before initqueue" |
53e1c5b9 | 203 | |
fa7ada31 | 204 | RDRETRY=$(getarg rd.retry 'rd_retry=') |
85fd75f9 HH |
205 | RDRETRY=${RDRETRY:-20} |
206 | RDRETRY=$(($RDRETRY*2)) | |
207 | ||
58dbb43e HH |
208 | i=0 |
209 | while :; do | |
58dbb43e | 210 | |
8238850c | 211 | check_finished && break |
3b403b32 | 212 | |
5c6a593f | 213 | udevsettle |
89056045 | 214 | |
8238850c HH |
215 | check_finished && break |
216 | ||
0b53ca70 HH |
217 | if [ -f $hookdir/initqueue/work ]; then |
218 | rm $hookdir/initqueue/work | |
58dbb43e | 219 | fi |
3b403b32 | 220 | |
0b53ca70 | 221 | for job in $hookdir/initqueue/*.sh; do |
cc02093d | 222 | [ -e "$job" ] || break |
58dbb43e | 223 | job=$job . $job |
8238850c | 224 | check_finished && break 2 |
58dbb43e HH |
225 | done |
226 | ||
8238850c | 227 | $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue |
71094bee | 228 | |
0b53ca70 | 229 | for job in $hookdir/initqueue/settled/*.sh; do |
040f3d2f HH |
230 | [ -e "$job" ] || break |
231 | job=$job . $job | |
232 | check_finished && break 2 | |
233 | done | |
234 | ||
235 | $UDEV_QUEUE_EMPTY >/dev/null 2>&1 || continue | |
236 | ||
8238850c HH |
237 | # no more udev jobs and queues empty. |
238 | sleep 0.5 | |
0e0bf830 HH |
239 | |
240 | # dirty hack for some cdrom drives, | |
241 | # which report no medium for quiet | |
242 | # some time. | |
9edf1b20 | 243 | for cdrom in /sys/block/sr*; do |
3b403b32 | 244 | [ -e "$cdrom" ] || continue |
5b2cc025 HH |
245 | # skip, if cdrom medium was already found |
246 | strstr "$(udevadm info --query=env --path=${cdrom##/sys})" \ | |
247 | ID_CDROM_MEDIA && continue | |
248 | ||
e620bb01 | 249 | if [ -e "$cdrom"/events_poll_msecs -a ! -e "/tmp/.poll_${cdrom##*/}" ]; then |
9edf1b20 | 250 | msecs=$(while read a; do echo $a;done < "$cdrom"/events_poll_msecs) |
5b2cc025 HH |
251 | if [ "$msecs" = "-1" ]; then |
252 | echo 250 > "$cdrom"/events_poll_msecs | |
253 | > "/tmp/.poll_${cdrom##*/}" | |
254 | fi | |
9edf1b20 | 255 | else |
5b2cc025 | 256 | echo change > "$cdrom/uevent" |
9edf1b20 HH |
257 | fi |
258 | done | |
3b403b32 | 259 | |
8238850c | 260 | i=$(($i+1)) |
85fd75f9 | 261 | [ $i -gt $RDRETRY ] \ |
a382492b | 262 | && { flock -s 9 ; emergency_shell "No root device \"$root\" found"; } 9>/.console_lock |
58dbb43e HH |
263 | done |
264 | unset job | |
265 | unset queuetriggered | |
ec9315e5 | 266 | |
9edf1b20 HH |
267 | # reset cdrom polling |
268 | for cdrom in /sys/block/sr*; do | |
3b403b32 | 269 | [ -e "$cdrom" ] || continue |
9edf1b20 HH |
270 | if [ -e "$cdrom"/events_poll_msecs ]; then |
271 | echo -1 > "$cdrom"/events_poll_msecs | |
272 | fi | |
273 | done | |
274 | ||
a08c1f45 VL |
275 | # pre-mount happens before we try to mount the root filesystem, |
276 | # and happens once. | |
fa7ada31 | 277 | getarg 'rd.break=pre-mount' 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break pre-mount" |
0b53ca70 | 278 | source_hook pre-mount |
bb040f93 | 279 | |
a3a3448d | 280 | |
fa7ada31 | 281 | getarg 'rd.break=mount' 'rdbreak=mount' && emergency_shell -n mount "Break mount" |
a08c1f45 VL |
282 | # mount scripts actually try to mount the root filesystem, and may |
283 | # be sourced any number of times. As soon as one suceeds, no more are sourced. | |
87930555 | 284 | i=0 |
a08c1f45 | 285 | while :; do |
37dcb400 | 286 | [ -d "$NEWROOT/proc" ] && break; |
0b53ca70 | 287 | for f in $hookdir/mount/*.sh; do |
cc02093d HH |
288 | [ -f "$f" ] && . "$f" |
289 | [ -d "$NEWROOT/proc" ] && break; | |
a08c1f45 | 290 | done |
bb040f93 | 291 | |
7cd15fe7 | 292 | i=$(($i+1)) |
a3a3448d HH |
293 | [ $i -gt 20 ] \ |
294 | && { flock -s 9 ; emergency_shell "Can't mount root filesystem"; } 9>/.console_lock | |
a08c1f45 VL |
295 | done |
296 | ||
0b2de1f8 HH |
297 | { |
298 | echo -n "Mounted root filesystem " | |
3b403b32 | 299 | while read dev mp rest; do [ "$mp" = "$NEWROOT" ] && echo $dev; done < /proc/mounts |
0b2de1f8 HH |
300 | } | vinfo |
301 | ||
b5c7c7e8 | 302 | # pre pivot scripts are sourced just before we switch over to the new root. |
fa7ada31 | 303 | getarg 'rd.break=pre-pivot' 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break pre-pivot" |
0b53ca70 | 304 | source_hook pre-pivot |
88ffd2df | 305 | |
a08c1f45 | 306 | # by the time we get here, the root filesystem should be mounted. |
d05f3c43 | 307 | # Try to find init. |
770b796e | 308 | for i in "$(getarg real_init=)" "$(getarg init=)" /sbin/init /etc/init /init /bin/sh; do |
2c1f37d4 | 309 | [ -n "$i" ] || continue |
7f7a91b7 HH |
310 | if ! [ -d "$NEWROOT$i" ] && [ -L "$NEWROOT$i" -o -x "$NEWROOT$i" ]; then |
311 | INIT="$i" | |
312 | break | |
313 | fi | |
d05f3c43 | 314 | done |
0b2de1f8 | 315 | |
6b0daf2e | 316 | [ "$INIT" ] || { |
a3a3448d HH |
317 | echo "Cannot find init!" |
318 | echo "Please check to make sure you passed a valid root filesystem!" | |
d05f3c43 | 319 | emergency_shell |
6b0daf2e | 320 | } |
a08c1f45 | 321 | |
fa7ada31 | 322 | getarg rd.break rdbreak && emergency_shell -n switch_root "Break before switch_root" |
7e87a0bf | 323 | |
6a168568 HH |
324 | if [ $UDEVVERSION -lt 168 ]; then |
325 | # stop udev queue before killing it | |
326 | udevadm control --stop-exec-queue | |
327 | ||
328 | HARD="" | |
3b403b32 | 329 | while pidof udevd >/dev/null 2>&1; do |
6a168568 HH |
330 | for pid in $(pidof udevd); do |
331 | kill $HARD $pid >/dev/null 2>&1 | |
332 | done | |
333 | HARD="-9" | |
7e87a0bf | 334 | done |
6a168568 HH |
335 | else |
336 | udevadm control --exit | |
337 | udevadm info --cleanup-db | |
338 | fi | |
5fa49940 | 339 | |
bf512ee2 | 340 | export RD_TIMESTAMP |
a6c34848 | 341 | set +x # Turn off debugging for this section |
5fa49940 AT |
342 | # Clean up the environment |
343 | for i in $(export -p); do | |
344 | i=${i#declare -x} | |
c79517b4 | 345 | i=${i#export} |
77e2cadd | 346 | strstr "$i" "=" || continue |
c79517b4 | 347 | i=${i%%=*} |
77e2cadd HH |
348 | [ -z "$i" ] && continue |
349 | case $i in | |
350 | root|PATH|HOME|TERM|PS4|RD_*) | |
351 | :;; | |
352 | *) | |
353 | unset "$i";; | |
354 | esac | |
5fa49940 AT |
355 | done |
356 | ||
faf88239 | 357 | initargs="" |
b63fd4d9 | 358 | read CLINE </proc/cmdline |
247c9f70 | 359 | if getarg init= >/dev/null ; then |
a6c34848 | 360 | set +x # Turn off debugging for this section |
247c9f70 HH |
361 | ignoreargs="console BOOT_IMAGE" |
362 | # only pass arguments after init= to the init | |
247c9f70 | 363 | CLINE=${CLINE#*init=} |
cc02093d HH |
364 | set $CLINE |
365 | shift | |
366 | for x in "$@"; do | |
3b403b32 | 367 | for s in $ignoreargs; do |
cc02093d HH |
368 | [ "${x%%=*}" = $s ] && continue 2 |
369 | done | |
370 | initargs="$initargs $x" | |
247c9f70 | 371 | done |
cc02093d | 372 | unset CLINE |
b63fd4d9 | 373 | else |
a6c34848 | 374 | set +x # Turn off debugging for this section |
b63fd4d9 AB |
375 | set $CLINE |
376 | shift | |
377 | for x in "$@"; do | |
378 | case "$x" in | |
cc02093d | 379 | [0-9]|s|S|single|emergency|auto ) \ |
b63fd4d9 | 380 | initargs="$initargs $x" |
cc02093d | 381 | ;; |
b63fd4d9 AB |
382 | esac |
383 | done | |
247c9f70 | 384 | fi |
dbad9f46 | 385 | [ "$RD_DEBUG" = "yes" ] && set -x |
3b403b32 | 386 | |
dbad9f46 HH |
387 | if [ -d "$NEWROOT"/run ]; then |
388 | NEWRUN="${NEWROOT}/run" | |
389 | mount --bind /run "$NEWRUN" | |
390 | NEWINITRAMFSROOT="$NEWRUN/initramfs" | |
e1ee9353 | 391 | |
dbad9f46 | 392 | if [ "$NEWINITRAMFSROOT/lib" -ef "/lib" ]; then |
3b403b32 | 393 | for d in bin etc lib lib64 sbin tmp usr var; do |
dbad9f46 HH |
394 | [ -h /$d ] && ln -fsn $NEWINITRAMFSROOT/$d /$d |
395 | done | |
396 | fi | |
397 | else | |
398 | NEWRUN=/dev/.initramfs | |
399 | mkdir -m 0755 "$NEWRUN" | |
400 | mount --bind /run/initramfs "$NEWRUN" | |
401 | fi | |
0b2de1f8 | 402 | |
ac36d5db | 403 | wait_for_loginit |
3b403b32 | 404 | |
dbad9f46 | 405 | info "Switching root" |
3b403b32 | 406 | |
dbad9f46 | 407 | umount -l /run |
4592b698 | 408 | |
dbad9f46 | 409 | unset PS4 |
19f3a804 | 410 | |
dbad9f46 HH |
411 | CAPSH=$(command -v capsh) |
412 | SWITCH_ROOT=$(command -v switch_root) | |
413 | PATH=$OLDPATH | |
414 | export PATH | |
98537743 | 415 | |
529349c6 HH |
416 | if [ -f /etc/capsdrop ]; then |
417 | . /etc/capsdrop | |
418 | info "Calling $INIT with capabilities $CAPS_INIT_DROP dropped." | |
9e7a3bf2 | 419 | unset RD_DEBUG |
dbad9f46 HH |
420 | exec $CAPSH --drop="$CAPS_INIT_DROP" -- \ |
421 | -c "exec switch_root \"$NEWROOT\" \"$INIT\" $initargs" || \ | |
422 | { | |
529349c6 HH |
423 | warn "Command:" |
424 | warn capsh --drop=$CAPS_INIT_DROP -- -c exec switch_root "$NEWROOT" "$INIT" $initargs | |
425 | warn "failed." | |
426 | emergency_shell | |
427 | } | |
428 | else | |
9e7a3bf2 | 429 | unset RD_DEBUG |
dbad9f46 | 430 | exec $SWITCH_ROOT "$NEWROOT" "$INIT" $initargs || { |
529349c6 HH |
431 | warn "Something went very badly wrong in the initramfs. Please " |
432 | warn "file a bug against dracut." | |
433 | emergency_shell | |
434 | } | |
435 | fi |