8 if [[ -n "$verbose" ]]; then
13 extraUtils
="@extraUtils@"
14 export LD_LIBRARY_PATH
=@extraUtils@
/lib
15 export PATH
=@extraUtils@
/bin
16 ln -s @extraUtils@
/bin
/bin
17 # hardcoded in util-linux's mount helper search path `/run/wrappers/bin:/run/current-system/sw/bin:/sbin`
18 ln -s @extraUtils@
/bin
/sbin
20 # Copy the secrets to their needed location
21 if [ -d "@extraUtils@/secrets" ]; then
22 for secret
in $
(cd "@extraUtils@/secrets"; find .
-type f
); do
23 mkdir
-p $
(dirname "/$secret")
24 ln -s "@extraUtils@/secrets/$secret" "$secret"
28 # Stop LVM complaining about fd3
29 export LVM_SUPPRESS_FD_WARNINGS
=true
32 if [ -n "$panicOnFail" ]; then exit 1; fi
36 # If starting stage 2 failed, allow the user to repair the problem
37 # in an interactive shell.
40 An error occurred in stage 1 of the boot process, which must mount the
41 root filesystem on \`$targetRoot' and then start stage 2. Press one
42 of the following keys:
45 if [ -n "$allowShell" ]; then cat <<EOF
46 i) to launch an interactive shell
47 f) to start an interactive shell having pid 1 (needed if you want to
48 start stage 2's init manually)
52 r) to reboot immediately
53 *) to ignore the error and continue
58 if [ -n "$allowShell" -a "$reply" = f
]; then
59 exec setsid @shell@
-c "exec @shell@ < /dev/$console >/dev/$console 2>/dev/$console"
60 elif [ -n "$allowShell" -a "$reply" = i
]; then
61 echo "Starting interactive shell..."
62 setsid @shell@
-c "exec @shell@ < /dev/$console >/dev/$console 2>/dev/$console" || fail
63 elif [ "$reply" = r
]; then
76 info
"\e[1;32m<<< @distroName@ Stage 1 >>>\e[0m"
79 # Make several required directories.
81 touch /etc
/fstab
# to shut up mount
82 ln -s /proc
/mounts
/etc
/mtab
# to shut up mke2fs
83 touch /etc
/udev
/hwdb.bin
# to shut up udev
84 touch /etc
/initrd-release
86 # Function for waiting for device(s) to appear.
89 # Split device string using ':' as a delimiter as bcachefs
90 # uses this for multi-device filesystems, i.e. /dev/sda1:/dev/sda2:/dev/sda3
93 # USB storage devices tend to appear with some delay. It would be
94 # great if we had a way to synchronously wait for them, but
95 # alas... So just wait for a few seconds for the device to
97 for dev
in $device; do
98 if test ! -e $dev; then
99 echo -n "waiting for device $dev to appear..."
101 while [ $try -gt 0 ]; do
103 # also re-try lvm activation now that new block devices might have appeared
105 # and tell udev to create nodes for the new LVs
106 udevadm trigger
--action=add
107 if test -e $dev; then break; fi
117 # Create the mount point if required.
120 local mountPoint
="$2"
125 # If we're bind mounting a file, the mount point should also be a file.
126 if ! [ -d "$device" ]; then
127 for opt
in $options; do
128 if [ "$opt" = bind ] ||
[ "$opt" = rbind
]; then
129 mkdir
-p "$(dirname "/mnt-root
$mountPoint")"
130 touch "/mnt-root$mountPoint"
136 mkdir
-m 0755 -p "/mnt-root$mountPoint"
139 # Mount special file systems.
142 local mountPoint
="$2"
146 mkdir
-m 0755 -p "$mountPoint"
147 mount
-n -t "$fsType" -o "$options" "$device" "$mountPoint"
149 source @earlyMountScript@
151 # Copy initrd secrets from /.initrd-secrets to their actual destinations
152 if [ -d "/.initrd-secrets" ]; then
154 # Secrets are named by their full destination pathname and stored
155 # under /.initrd-secrets/
157 for secret
in $
(cd "/.initrd-secrets"; find .
-type f
); do
158 mkdir
-p $
(dirname "/$secret")
159 cp "/.initrd-secrets/$secret" "$secret"
163 # Log the script output to /dev/kmsg or /run/log/stage-1-init.log.
165 mkfifo /tmp
/stage-1-init.log.fifo
166 logOutFd
=8 && logErrFd
=9
167 eval "exec $logOutFd>&1 $logErrFd>&2"
168 if test -w /dev
/kmsg
; then
169 tee -i < /tmp
/stage-1-init.log.fifo
/proc
/self
/fd
/"$logOutFd" |
while read -r line
; do
170 if test -n "$line"; then
171 echo "<7>stage-1-init: [$(date)] $line" > /dev
/kmsg
176 tee -i < /tmp
/stage-1-init.log.fifo
/run
/log
/stage-1-init.log
&
178 exec > /tmp
/stage-1-init.log.fifo
2>&1
181 # Process the kernel command line.
182 export stage2Init
=/init
183 for o
in $
(cat /proc
/cmdline
); do
186 set -- $
(IFS
==; echo $o)
188 set -- $
(IFS
=,; echo $params)
192 set -- $
(IFS
==; echo $o)
196 set -- $
(IFS
==; echo $o)
199 boot.persistence.opt
=*)
200 set -- $
(IFS
==; echo $o)
203 boot.trace|debugtrace
)
210 boot.debug1|debug1
) # stop right away
214 boot.debug1devices
) # stop after loading modules and creating device nodes
218 boot.debug1mounts
) # stop after mounting file systems
222 boot.panic_on_fail|stage1panic
=1)
226 # If a root device is specified on the kernel command
227 # line, make it available through the symlink /dev/root.
228 # Recognise LABEL= and UUID= to support UNetbootin.
229 set -- $
(IFS
==; echo $o)
230 if [ $2 = "LABEL" ]; then
231 root
="/dev/disk/by-label/$3"
232 elif [ $2 = "UUID" ]; then
233 root
="/dev/disk/by-uuid/$3"
237 ln -s "$root" /dev
/root
243 # if an iso name is supplied, try to find the device where
245 set -- $
(IFS
==; echo $o)
251 # Set hostid before modules are loaded.
252 # This is needed by the spl/zfs modules.
255 # Load the required kernel modules.
256 echo @extraUtils@
/bin
/modprobe
> /proc
/sys
/kernel
/modprobe
257 for i
in @kernelModules@
; do
258 info
"loading module $(basename $i)..."
263 # Create device nodes in /dev.
265 info
"running udev..."
266 ln -sfn /proc
/self
/fd
/dev
/fd
267 ln -sfn /proc
/self
/fd
/0 /dev
/stdin
268 ln -sfn /proc
/self
/fd
/1 /dev
/stdout
269 ln -sfn /proc
/self
/fd
/2 /dev
/stderr
270 mkdir
-p /etc
/systemd
271 ln -sfn @linkUnits@
/etc
/systemd
/network
273 ln -sfn @udevRules@
/etc
/udev
/rules.d
275 systemd-udevd
--daemon
276 udevadm trigger
--action=add
280 # XXX: Use case usb->lvm will still fail, usb->luks->lvm is covered
283 info
"starting device mapper and LVM..."
286 if test -n "$debug1devices"; then fail
; fi
292 # Check the specified file system, if appropriate.
297 # Only check block devices.
298 if [ ! -b "$device" ]; then return 0; fi
300 # Don't check ROM filesystems.
301 if [ "$fsType" = iso9660
-o "$fsType" = udf
]; then return 0; fi
303 # Don't check resilient COWs as they validate the fs structures at mount time
304 if [ "$fsType" = btrfs
-o "$fsType" = zfs
-o "$fsType" = bcachefs
]; then return 0; fi
306 # Skip fsck for apfs as the fsck utility does not support repairing the filesystem (no -a option)
307 if [ "$fsType" = apfs
]; then return 0; fi
309 # Skip fsck for nilfs2 - not needed by design and no fsck tool for this filesystem.
310 if [ "$fsType" = nilfs2
]; then return 0; fi
312 # Skip fsck for inherently readonly filesystems.
313 if [ "$fsType" = squashfs
]; then return 0; fi
315 # Skip fsck.erofs because it is still experimental.
316 if [ "$fsType" = erofs
]; then return 0; fi
318 # If we couldn't figure out the FS type, then skip fsck.
319 if [ "$fsType" = auto
]; then
320 echo 'cannot check filesystem with type "auto"!'
324 # Device might be already mounted manually
325 # e.g. NBD-device or the host filesystem of the file which contains encrypted root fs
326 if mount |
grep -q "^$device on "; then
327 echo "skip checking already mounted $device"
331 # Optionally, skip fsck on journaling filesystems. This option is
332 # a hack - it's mostly because e2fsck on ext3 takes much longer to
333 # recover the journal than the ext3 implementation in the kernel
334 # does (minutes versus seconds).
335 if test -z "@checkJournalingFS@" -a \
336 \
( "$fsType" = ext3
-o "$fsType" = ext4
-o "$fsType" = reiserfs \
337 -o "$fsType" = xfs
-o "$fsType" = jfs
-o "$fsType" = f2fs \
)
342 echo "checking $device..."
347 if test $
(($fsckResult |
2)) = $fsckResult; then
348 echo "fsck finished, rebooting..."
353 if test $
(($fsckResult |
4)) = $fsckResult; then
354 echo "$device has unrepaired errors, please fix them manually."
358 if test $fsckResult -ge 8; then
359 echo "fsck on $device failed."
370 local escaped
="${original// /\\040}"
372 echo "${escaped//$'\t'/\\011}"
375 # Function for mounting a file system.
378 local mountPoint
="$2"
382 if [ "$fsType" = auto
]; then
383 fsType
=$
(blkid
-o value
-s TYPE
"$device")
384 if [ -z "$fsType" ]; then fsType
=auto
; fi
387 # Filter out x- options, which busybox doesn't do yet.
388 local optionsFiltered
="$(IFS=,; for i in $options; do if [ "${i:0:2}" != "x-
" ]; then echo -n $i,; fi; done)"
389 # Prefix (lower|upper|work)dir with /mnt-root (overlayfs)
390 local optionsPrefixed
="$( echo "$optionsFiltered" | sed -E 's#\<(lowerdir|upperdir|workdir)=#\1=/mnt-root#g' )"
392 echo "$device /mnt-root$mountPoint $fsType $optionsPrefixed" >> /etc
/fstab
394 checkFS
"$device" "$fsType"
396 # Create backing directories for overlayfs
397 if [ "$fsType" = overlay
]; then
398 for i
in upper work
; do
399 dir
="$( echo "$optionsPrefixed" | grep -o "${i}dir
=[^
,]*" )"
400 mkdir
-m 0700 -p "${dir##*=}"
404 info
"mounting $device on $mountPoint..."
406 makeMountPoint
"$device" "$mountPoint" "$optionsPrefixed"
408 # For ZFS and CIFS mounts, retry a few times before giving up.
409 # We do this for ZFS as a workaround for issue NixOS/nixpkgs#25383.
412 mount
"/mnt-root$mountPoint" && break
413 if [ \
( "$fsType" != cifs
-a "$fsType" != zfs \
) -o "$n" -ge 10 ]; then fail
; break; fi
419 # For bind mounts, busybox has a tendency to ignore options, which can be a
420 # security issue (e.g. "nosuid"). Remounting the partition seems to fix the
422 mount
"/mnt-root$mountPoint" -o "remount,$optionsPrefixed"
424 [ "$mountPoint" == "/" ] &&
425 [ -f "/mnt-root/etc/NIXOS_LUSTRATE" ] &&
426 lustrateRoot
"/mnt-root"
435 echo -e "\e[1;33m<<< @distroName@ is now lustrating the root filesystem (cruft goes to /old-root) >>>\e[0m"
438 mkdir
-m 0755 -p "$root/old-root.tmp"
441 echo "Moving impurities out of the way:"
444 [ "$d" == "$root/nix" ] && continue
445 [ "$d" == "$root/boot" ] && continue # Don't render the system unbootable
446 [ "$d" == "$root/old-root.tmp" ] && continue
448 mv -v "$d" "$root/old-root.tmp"
451 # Use .tmp to make sure subsequent invocations don't clash
452 mv -v "$root/old-root.tmp" "$root/old-root"
454 mkdir
-m 0755 -p "$root/etc"
455 touch "$root/etc/NIXOS"
457 exec 4< "$root/old-root/etc/NIXOS_LUSTRATE"
460 echo "Restoring selected impurities:"
461 while read -u 4 keeper
; do
462 dirname="$(dirname "$keeper")"
463 mkdir
-m 0755 -p "$root/$dirname"
464 cp -av "$root/old-root/$keeper" "$root/$keeper"
472 if test -e /sys
/power
/resume
-a -e /sys
/power
/disk
; then
473 if test -n "@resumeDevice@" && waitDevice
"@resumeDevice@"; then
474 resumeDev
="@resumeDevice@"
475 resumeInfo
="$(udevadm info -q property "$resumeDev" )"
477 for sd
in @resumeDevices@
; do
478 # Try to detect resume device. According to Ubuntu bug:
479 # https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/923326/comments/1
480 # when there are multiple swap devices, we can't know where the hibernate
481 # image will reside. We can check all of them for swsuspend blkid.
482 if waitDevice
"$sd"; then
483 resumeInfo
="$(udevadm info -q property "$sd")"
484 if [ "$(echo "$resumeInfo" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then
491 if test -n "$resumeDev"; then
492 resumeMajor
="$(echo "$resumeInfo" | sed -n 's/^MAJOR=//p')"
493 resumeMinor
="$(echo "$resumeInfo" | sed -n 's/^MINOR=//p')"
494 echo "$resumeMajor:$resumeMinor" > /sys
/power
/resume
2> /dev
/null ||
echo "failed to resume..."
500 # If we have a path to an iso file, find the iso and link it to /dev/root
501 if [ -n "$isoPath" ]; then
504 for delay
in 5 10; do
505 blkid |
while read -r line
; do
506 device
=$
(echo "$line" |
sed 's/:.*//')
507 type=$
(echo "$line" |
sed 's/.*TYPE="\([^"]*\)".*/\1/')
509 mount
-t "$type" "$device" /findiso
510 if [ -e "/findiso$isoPath" ]; then
511 ln -sf "/findiso$isoPath" /dev
/root
522 # Try to find and mount the root device.
527 while read -u 3 mountPoint
; do
532 # !!! Really quick hack to support bind mounts, i.e., where the
533 # "device" should be taken relative to /mnt-root, not /. Assume
534 # that every device that starts with / but doesn't start with /dev
541 # Don't touch SMB/CIFS paths.
545 device
=/mnt-root
$device
548 # Not an absolute path; assume that it's a pseudo-device
549 # like an NFS path (e.g. "server:/path").
554 if test -z "$pseudoDevice" && ! waitDevice
"$device"; then
555 # If it doesn't appear, try to mount it anyway (and
556 # probably fail). This is a fallback for non-device "devices"
557 # that we don't properly recognise.
558 echo "Timed out waiting for device $device, trying to mount anyway."
561 # Wait once more for the udev queue to empty, just in case it's
562 # doing something with $device right now.
565 # If copytoram is enabled: skip mounting the ISO and copy its content to a tmpfs.
566 if [ -n "$copytoram" ] && [ "$device" = /dev
/root
] && [ "$mountPoint" = /iso
]; then
567 fsType
=$
(blkid
-o value
-s TYPE
"$device")
568 fsSize
=$
(blockdev
--getsize64 "$device" || stat
-Lc '%s' "$device")
571 mount
-t "$fsType" /dev
/root
/tmp-iso
572 mountFS tmpfs
/iso size
="$fsSize" tmpfs
574 cp -r /tmp-iso
/* /mnt-root
/iso
/
578 if [ -n "$isoPath" ] && [ $fsType = "iso9660" ] && mountpoint
-q /findiso
; then
584 if [ "$mountPoint" = / ] && [ "$device" = tmpfs
] && [ ! -z "$persistence" ]; then
586 waitDevice
"$persistence"
587 echo enabling persistence...
588 mountFS
"$persistence" "$mountPoint" "$persistence_opt" "auto"
592 mountFS
"$device" "$(escapeFstab "$mountPoint")" "$(escapeFstab "$options")" "$fsType"
601 # Emit a udev rule for /dev/root to prevent systemd from complaining.
602 if [ -e /mnt-root
/iso
]; then
603 eval $
(udevadm info
--export --export-prefix=ROOT_
--device-id-of-file=/mnt-root
/iso
)
605 eval $
(udevadm info
--export --export-prefix=ROOT_
--device-id-of-file=$targetRoot)
607 if [ "$ROOT_MAJOR" -a "$ROOT_MINOR" -a "$ROOT_MAJOR" != 0 ]; then
608 mkdir
-p /run
/udev
/rules.d
609 echo 'ACTION=="add|change", SUBSYSTEM=="block", ENV{MAJOR}=="'$ROOT_MAJOR'", ENV{MINOR}=="'$ROOT_MINOR'", SYMLINK+="root"' > /run
/udev
/rules.d
/61-dev-root-link.rules
614 udevadm control
--exit
616 # Reset the logging file descriptors.
617 # Do this just before pkill, which will kill the tee process.
618 exec 1>&$logOutFd 2>&$logErrFd
619 eval "exec $logOutFd>&- $logErrFd>&-"
621 # Kill any remaining processes, just to be sure we're not taking any
622 # with us into stage 2. But keep storage daemons like unionfs-fuse.
624 # Storage daemons are distinguished by an @ in front of their command line:
625 # https://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/
626 for pid
in $
(pgrep
-v -f '^@'); do
627 # Make sure we don't kill kernel processes, see #15226 and:
628 # http://stackoverflow.com/questions/12213445/identifying-kernel-threads
629 readlink
"/proc/$pid/exe" &> /dev
/null ||
continue
630 # Try to avoid killing ourselves.
631 [ $pid -eq $$
] && continue
635 if test -n "$debug1mounts"; then fail
; fi
638 # Restore /proc/sys/kernel/modprobe to its original value.
639 echo /sbin
/modprobe
> /proc
/sys
/kernel
/modprobe
642 # Start stage 2. `switch_root' deletes all files in the ramfs on the
643 # current root. The path has to be valid in the chroot not outside.
644 if [ ! -e "$targetRoot/$stage2Init" ]; then
645 stage2Check
=${stage2Init}
646 while [ "$stage2Check" != "${stage2Check%/*}" ] && [ ! -L "$targetRoot/$stage2Check" ]; do
647 stage2Check
=${stage2Check%/*}
649 if [ ! -L "$targetRoot/$stage2Check" ]; then
650 echo "stage 2 init script ($targetRoot/$stage2Init) not found"
655 mkdir
-m 0755 -p $targetRoot/proc
$targetRoot/sys
$targetRoot/dev
$targetRoot/run
657 mount
--move /proc
$targetRoot/proc
658 mount
--move /sys
$targetRoot/sys
659 mount
--move /dev
$targetRoot/dev
660 mount
--move /run
$targetRoot/run
662 exec env
-i $
(type -P switch_root
) "$targetRoot" "$stage2Init"
664 fail
# should never be reached