#!/bin/sh -ef # # tiny init # # word splitting is safe by design # shellcheck disable=2068,2046,2086 # # false positive # shellcheck disable=2154,2163,1091 print() { printf "%b %s\n" "${2:-"\033[1;37m>>\033[m"}" "$1" } panic() { print "${1:-unexpected error occurred}" \ "\033[1;31m!!\033[m" >&2; sh } findfs() { count=0; device= case "${1%%=*}" in /dev/*) device="$1" ;; UUID) device="/dev/disk/by-uuid/${1##*=}" ;; LABEL) device="/dev/disk/by-label/${1##*=}" ;; PARTUUID) device="/dev/disk/by-partuuid/${1##*=}" ;; esac # prevent race condition while [ ! -e "$device" ]; do sleep 1 [ "$(( count += 1 ))" != 30 ] || { panic "failed to lookup partition" break } done } prepare_environment() { . /etc/tinyramfs/config export \ PATH=/bin TERM=linux SHELL=/bin/sh \ LANG=C LC_ALL=C PS1="# " HOME=/root \ mount -t proc -o nosuid,noexec,nodev proc /proc mount -t sysfs -o nosuid,noexec,nodev sys /sys mount -t tmpfs -o nosuid,nodev,mode=0755 run /run mount -t devtmpfs -o nosuid,noexec,mode=0755 dev /dev mkdir -p \ /run/cryptsetup \ /run/lock \ /run/lvm ln -s /proc/self/fd /dev/fd ln -s fd/0 /dev/stdin ln -s fd/1 /dev/stdout ln -s fd/2 /dev/stderr trap panic EXIT [ ! "$modules" ] || modprobe -a "$modules" } parse_cmdline() { read -r cmdline < /proc/cmdline for line in $cmdline; do case "$line" in debug | debug=1) set -x ;; rootfstype=*) root_type="${line##*=}" ;; rootflags=*) root_opts="${line##*=}" ;; ro | rw) rorw="-o $line" ;; --) init_args="${cmdline##*--}"; break ;; *=*) export "$line" ;; *) export "${line}=1" ;; esac; done } setup_devmgr() { [ "$break" = devmgr ] && { print "break before setup_devmgr()"; sh; } case "$devmgr" in udev) udevd -N never & devmgr_pid="$!" udevadm trigger -c add -t subsystems udevadm trigger -c add -t devices udevadm settle ;; mdev) mdev -s mdev -df & devmgr_pid="$!" [ "$monolith" = 1 ] && return 0 find /sys/devices -name uevent | while read -r uevent; do printf add > "$uevent" done ;; mdevd) mdevd & devmgr_pid="$!" mdevd-coldplug ;; esac 2> /dev/null } unlock_luks() { [ "$break" = luks ] && { print "break before unlock_luks()"; sh; } { IFS=,; set -- $luks_opts; unset IFS; } for opt; do case "$opt" in discard | discard=1) luks_discard="--allow-discards" ;; header=*) luks_header="--${opt}" ;; name=*) luks_name="${opt##*=}" ;; key=*) luks_key="-d ${opt##*=}" ;; esac; done findfs "$luks_root" set -- \ "$luks_key" "$luks_header" "$luks_discard" \ "$device" "${luks_name:-luks-${device##*/}}" cryptsetup open $@ || panic "failed to unlock LUKS" } trigger_lvm() { [ "$break" = lvm ] && { print "break before trigger_lvm()"; sh; } { IFS=,; set -- $lvm_opts; unset IFS; } for opt; do case "$opt" in discard | discard=1) lvm_discard="--config=devices{issue_discards=1}" ;; config=0) : > /etc/lvm/lvm.conf ;; group=*) lvm_group="${opt##*=}" ;; name=*) lvm_name="/${opt##*=}" ;; tag=*) lvm_tag="@${opt##*=}" ;; esac; done set -- "--sysinit" "-qq" "-aay" "$lvm_discard" if [ "$lvm_group" ] && [ "$lvm_name" ]; then lvm lvchange $@ "${lvm_group}${lvm_name}" elif [ "$lvm_group" ]; then lvm vgchange $@ "$lvm_group" elif [ "$lvm_tag" ]; then lvm lvchange $@ "$lvm_tag" else lvm vgchange $@ fi [ "$?" = 0 ] || panic "failed to trigger LVM" } mount_root() { [ "$break" = root ] && { print "break before mount_root()"; sh; } findfs "$root" set -- \ "${rorw:--o ro}${root_opts:+,$root_opts}" \ "${root_type:+-t $root_type}" "$device" "/mnt/root" mount $@ || panic "failed to mount root" } boot_system() { [ "$break" = boot ] && { print "break before boot_system()"; sh; } kill "$devmgr_pid" # temporary workaround until util-linux release a new version # see https://github.com/karelzak/util-linux/issues/997 for dir in run dev sys proc; do mount -o move "$dir" "/mnt/root/${dir}" || mount --move "$dir" "/mnt/root/${dir}" done set -- \ "/mnt/root" "${init:-/sbin/init}" "$init_args" exec switch_root $@ || panic "failed to boot system" } # int main() { prepare_environment parse_cmdline setup_devmgr # trigger lvm twice to handle both LUKS on LVM and LVM on LUKS [ "$lvm" = 1 ] && trigger_lvm [ "$luks" = 1 ] && unlock_luks [ "$lvm" = 1 ] && trigger_lvm mount_root boot_system }