281 lines
6.0 KiB
Bash
Executable File
281 lines
6.0 KiB
Bash
Executable File
#!/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
|
|
|
|
shell
|
|
}
|
|
|
|
shell()
|
|
{
|
|
# see https://busybox.net/FAQ.html#job_control
|
|
setsid sh -c "exec sh <> /dev/${console:-tty1} 2>&1" || 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
|
|
|
|
# avoid race condition
|
|
while [ ! -e "$device" ]; do
|
|
sleep 1; : $(( count += 1 ))
|
|
|
|
[ "$count" = 30 ] && {
|
|
panic "failed to lookup partition"
|
|
break
|
|
}
|
|
done || :
|
|
}
|
|
|
|
prepare_environment()
|
|
{
|
|
. /etc/tinyramfs/config
|
|
|
|
export \
|
|
LANG=C \
|
|
PS1="# " \
|
|
LC_ALL=C \
|
|
TERM=linux \
|
|
HOME=/root \
|
|
SHELL=/bin/sh \
|
|
OLD_IFS="$IFS" \
|
|
PATH=/bin:/sbin:/usr/bin:/usr/sbin
|
|
|
|
# fix for ubase mount
|
|
: > /etc/fstab
|
|
|
|
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" ] || return 0
|
|
|
|
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"
|
|
;;
|
|
*.*)
|
|
# TODO implement backward compatibilty with dracut, mkinitcpio, etc
|
|
: no operation
|
|
;;
|
|
*=*)
|
|
export "$line" || :
|
|
;;
|
|
*)
|
|
export "${line}=1" || :
|
|
;;
|
|
esac; done
|
|
}
|
|
|
|
setup_devmgr()
|
|
{
|
|
[ "$break" = devmgr ] && { print "break before setup_devmgr()"; shell; }
|
|
|
|
case "$devmgr" in
|
|
udev)
|
|
udevd -dN never
|
|
udevadm trigger -c add -t subsystems
|
|
udevadm trigger -c add -t devices
|
|
udevadm settle
|
|
;;
|
|
mdev)
|
|
mdev -df 2> /dev/null & mdev_pid="$!"
|
|
mdev -s
|
|
|
|
[ "$monolith" = 1 ] && return 0
|
|
|
|
# TODO maybe replace sort using while-read loop
|
|
# while-read can cause slowdown, so why i'm unsure
|
|
set -- $(find /sys -name modalias -type f -exec sort -u {} +)
|
|
modprobe -a "$@" 2> /dev/null || :
|
|
;;
|
|
mdevd)
|
|
mdevd 2> /dev/null & mdevd_pid="$!"
|
|
mdevd-coldplug
|
|
;;
|
|
esac
|
|
}
|
|
|
|
unlock_luks()
|
|
{
|
|
[ "$break" = luks ] && { print "break before unlock_luks()"; shell; }
|
|
|
|
{ IFS=,; set -- $luks_opts; IFS="$OLD_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()"; shell; }
|
|
|
|
{ IFS=,; set -- $lvm_opts; IFS="$OLD_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
|
|
}
|
|
|
|
mount_root()
|
|
{
|
|
[ "$break" = root ] && { print "break before mount_root()"; shell; }
|
|
|
|
findfs "$root"
|
|
|
|
set -- \
|
|
"${root_type:+-t $root_type}" \
|
|
"${rorw:--o ro}${root_opts:+,$root_opts}" \
|
|
"$device" "/mnt/root"
|
|
|
|
mount $@ || panic "failed to mount root"
|
|
}
|
|
|
|
cleanup()
|
|
{
|
|
[ "$break" = cleanup ] && { print "break before cleanup()"; shell; }
|
|
|
|
case "$devmgr" in
|
|
udev) udevadm control -e ;;
|
|
mdev) kill "$mdev_pid" ;;
|
|
mdevd) kill "$mdevd_pid" ;;
|
|
esac
|
|
|
|
# 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
|
|
}
|
|
|
|
boot_system()
|
|
{
|
|
[ "$break" = boot ] && { print "break before boot_system()"; shell; }
|
|
|
|
set -- "/mnt/root" "${init:-/sbin/init}"
|
|
exec switch_root $@ 2> /dev/null || 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
|
|
cleanup
|
|
boot_system
|
|
}
|