The Unix Heritage Society mailing list
 help / color / mirror / Atom feed
From: Steffen Nurpmeso <steffen@sdaoden.eu>
To: "Michael Kjörling" <e5655f30a07f@ewoof.net>
Cc: tuhs@tuhs.org
Subject: [TUHS] Re: Unix install & "standalone" package
Date: Sun, 10 Sep 2023 00:43:12 +0200	[thread overview]
Message-ID: <20230909224312.gGToQ%steffen@sdaoden.eu> (raw)
In-Reply-To: <20230908233854.Xni_j%steffen@sdaoden.eu>

[-- Attachment #1: Type: text/plain, Size: 7275 bytes --]

Steffen Nurpmeso wrote in
 <20230908233854.Xni_j%steffen@sdaoden.eu>:
 |Michael Kjörling wrote in
 | <f948d06c-14f4-40bd-8e32-4db1c5b1dd21@home.arpa>:
 ||On 5 Sep 2023 17:53 +0200, from steffen@sdaoden.eu (Steffen Nurpmeso):
 ...
 ||> Of course i am no real Linux expert but only a do-it-yourself guy.
 ||
 ||If your need is restricted to a highly specific use case and you are
 ||trying to keep it as small as possible, then it should be possible to
 ...

Actually maybe someone may find it funny, even though it is
neither historic nor very sophisticated.  Let me post it.
In the end it takes some time to get there.


I would expect almost all of you will not be interested in the
lengthy rest of this mail.
Ciao, and a nice Sunday i wish from Germany!


All you need are statically linked busybox (and cryptsetup with
encryption), and a kernel with EFI_STUB on the EFI partition, so
it can be booted directly.  The distribution kernels i have
(ArchLinux, AlpineLinux) have it enabled; if your EFI is large
enough you could simply copy it and all its masses of modules to
EFI.

Otherwise the kernel needs all the firmware and modules to boot
and to access all filesystems where the real stuff is.  My own
kernel has a lot of things statically built-in, but it can load
more via modules (stage2 uses "the same" kernel later, and does).
Kernels on stage2 need kexec, i have

  CONFIG_KEXEC=y
  CONFIG_KEXEC_FILE=y
  CONFIG_ARCH_HAS_KEXEC_PURGATORY=y
  # CONFIG_KEXEC_SIG is not set
  CONFIG_KEXEC_CORE=y

-s1.sh and -s2.sh are docu-commented at the top; they can also be
used to create the necessary environment.  If i recall correctly

  cd /boot
  sh linit-init-s2.sh PATH-TO-BUSYBOX PATH-TO-CRYPTSETUP
  mount EFI-PARTITION
  cd EFI-PARTITION
  sh linit-init-s1.sh PATH-TO-BUSYBOX PATH-TO-CRYPTSETUP

This only creates files and directories etc, and beat me if it
does any harm otherwise.

I use a specific naming scheme, the script reacts in particular
on -old and -new to select sensible defaults.

  #?0|kent:/boot# ll ideapad*.efi
  -rwxr-xr-x 1 root root 10112672 Aug 26 18:44 ideapad-stage1.efi*
  -rw-r--r-- 1 root root 10120512 Sep  2 19:52 ideapad-6_1.efi
  -rw-r--r-- 1 root root 10120512 Sep  9 18:18 ideapad-6_1-old.efi
  -rw-r--r-- 1 root root 10121376 Sep  9 18:18 ideapad-6_1-new.efi

That very kernel (series) is in fact shared in between several
computers of a similar series, kent is the one i write this on:

  #?1|kent:/boot# v kent.sh
  #!/busybox.static sh
  #@ kent, step 1., via EFI.
  PART_ROOT=/dev/nvme0n1p?
  ROOT_DECRYPT='-t btrfs -o defaults,subvol=/crux/kent/root'
  	PART_ROOT1=/dev/nvme0n1p8
  	ROOT_DECRYPT1='-t btrfs -o defaults,subvol=/crux/kent/root.old'
  INIT_S2=/boot/kent-2.sh
  . /linux-init-s1.sh

  #?0|kent:/boot# v kent-2.sh
  #@ kent, stage 2
  KERNEL_ID=ideapad

^ restrict kernel selection for kexec:
^      	[ "${k##*$KERNEL_ID-*.efi}" != "$k" ] || continue

  PART_SWAP=/dev/nvme0n1p6
  SWAP_INPUT=y

^ you can have additional interactive random for swap encryption
^ (it is a lie i use that in practice)

  INITRD_PATH=/boot/.kent.initrd
  KEXEC_ARGS="--append=\"rtw88_pci.disable_aspm=1 rc.hostname=kent\""
  FILE_CHECK='kent-direct.sh kent.sh ideapad-stage1.efi'
  SWITCH_ROOT=media/initrd

Stage 2 config file is sourced automatically, so no need to source
linux-init-s2.sh yourself (stage 2 uses switch_root).
I also have a direct boot, but have not used it for long:

  #?0|kent:~# v /boot/kent-direct.sh
  #!/busybox.static sh
  #@ kent-direct, sole step 1., via EFI.
  PART_ROOT=/dev/nvme0n1p8
  ROOT_DECRYPT='-t btrfs -o defaults,subvol=/crux/kent/root'
  	PART_ROOT1=/dev/nvme0n1p8
  	ROOT_DECRYPT1='-t btrfs -o defaults,subvol=/crux/kent/root.old'
  PART_SWAP=/dev/nvme0n1p6
  PIVOT_OLDROOT=media/initrd
  . /linux-init-s1.sh

This does not use kexec, but only pivot_root's to the decrypted
filesystem, starting sbin/init there.  The kernel from EFI
continues to run.

It is pretty cool how i now can drive several computers easily
simply by creating a shell script with some variable assignments.
In fact the filesystem is shared in between multiple computers
(with only selective partitions being truly unique, but still
backed up everywhere), and all those text configs are in /boot.
Only the VFAT EFI partition is truly system-specific (ie, in that
it only holds the stage1 config file for $HOSTNAME).

I like that very much, and hope Linux continues to be so flexible.
(Not that one day you need systemd-early to get into Linux to get
to systemd-later, or something.)

The EFI boot is driven via efibootmgr(8) and has config like

  #@ /root/hosts/self/efiboot
  d=/dev/nvme0n1p1
  maxno=1

  b1=0x01  L1=kent  l1=ideapad-stage1
  u1='root='${d}' rootfstype=vfat init=/kent.sh'

driven by /root/bin/efiboot.sh (shortened):

  #!/bin/sh
  : ${HOSTNAME:=$(uname -n)}
  : ${DBG:=}
  if [ -f /root/hosts/${HOSTNAME}/efiboot ]; then
          . /root/hosts/${HOSTNAME}/efiboot
  else
          echo >&2 "MISS /root/hosts/${HOSTNAME}/efiboot"
          exit 1
  fi
  if [ "$1" = create ]; then
          obo=$(efibootmgr | grep -E ^BootOrder: | sed -E 's/^BootOrder:[[:space:]]*//')
          if [ -z "$obo" ]; then
                  echo >&2 'Cannot determine previous boot order'
                  exit 1
          fi
          nbo= i=1
          while [ $i -le $maxno ]; do
                  eval ${DBG} efibootmgr -c -b \$b$i -L \\\"\$L$i\\\" -d \$d$i -l \\\"\$l$i.efi\\\" -u \\\"\$u$i\\\" #>/dev/null
                  [ -n "$nbo" ] && nbo=$nbo,
                  eval nbo=\$nbo\$b$i
                  i=$((i + 1))
          done
          ${DBG} efibootmgr -o $nbo,$obo #> /dev/null
  elif [ "$1" = delete ]; then
          i=1
          while [ $i -le $maxno ]; do
                  eval ${DBG} efibootmgr -B -b \$b$i #>/dev/null
                  i=$((i + 1))
          done
  else
          echo >&2 'Synsopsis: efiboot.sh create|delete'
          exit 1
  fi

  ${DBG} efibootmgr -v -u

This is of course git managed, so i can distribute it easily.
(Further even, the entire ideapad series configurations differ in
only 193 lines, and most of those are the different SSH keys.
The rest are different device names, ie network, display, volume
etc, disk partitions, host names.)

I am pretty lucky i found a way to manage my systems like this.
I have several git branches in root.git, linux.kconfig, bin,
iwd.network, and one for each computer.  I can then "git merge"
selectively together what is necessary.  For example my web
vserver only needs bin and its own configuration, whereas the
laptops also need iwd.network.  Etc etc.  Like this every computer
only knows the selective minimum.  The full git repo is on an
encrypted volume stored away.
And it is not Puppet or Ansible or any of those programs, it is
nothing but git and its branches.
But now i really left manually driven cryptsetup by far.
Ciao!

--steffen
|
|Der Kragenbaer,                The moon bear,
|der holt sich munter           he cheerfully and one by one
|einen nach dem anderen runter  wa.ks himself off
|(By Robert Gernhardt)

[-- Attachment #2: linux-init-s1.sh --]
[-- Type: application/x-sh, Size: 4596 bytes --]

#@ /linux-init-s1.sh, simple Linux init, stage 1.
#@ To be sourced from a kernel command line init=SCRIPT like:
#@
#@   #!/busybox.static sh
#@   #@ For kent
#@
#@   PART_ROOT=/dev/nvme0n1p8
#@   ROOT_DECRYPT='-t btrfs -o defaults,subvol=/crux/kent/root'
#@   PART_SWAP=/dev/nvme0n1p6
#@   INIT_S2=boot/kent-2.sh
#@
#@   . /linux-init-s1.sh
#@
#@ Alternatively call AS ROOT and FROM WITHIN directory that boots like
#@   sh linux-init-s1.sh PATH_TO_BUSYBOX PATH_TO_CRYPTSETUP
#@ and is expected to be mounted as / on system start, for init purposes.

# Non-empty and we run mdev -s very first (value passed to it via ARGV)
: ${MDEV_RUN:=}

# Unless ROOT_DECRYPT (only partition then) this can be mount spec, like
#		PART_ROOT='-t btrfs -o defaults,subvol=/crux/kent/root'
[ $# -eq 0 ] &&
	: ${PART_ROOT:?"Need a usable \$PART_ROOT"}
# Non-empty and we decrypt ROOT; _it_ should be mount spec then
: ${ROOT_DECRYPT:=}
# It is possible to specify multiple PART_ROOT[/ROOT_DECRYPT] tuples by
# giving PART_ROOT1, 2, 3...	A dialog for choosing one to use then appears

# Non-empty and we create encrypted swap from the given partition
: ${PART_SWAP:=}
# Non-empty and we ask for more random bytes for swap encryption
: ${SWAP_INPUT:=}

# Non-empty and we give up to the stage 2 -s2.sh that is expected to live
# in [/dev/mapper/p_root]/boot.	ONLY WITH $ROOT_DECRYPT!
# The value is the config file of stage 2 as an _absolute_ path within the
# newly mounted root.
: ${INIT_S2:=}

# Were we move old root to when doing pivot_root(8) in non-$INIT_S2 cases
: ${PIVOT_OLDROOT:=media/efi}

BB=busybox.static
CS=cryptsetup.static

# -- >8 -- 8< --

xroot() { # {{{
	bb=./$BB cs=./$CS
	slept= # May want to sleep to pass by kernel async console output

	xbase_mounts "$bb" # (First for completeness sake [not needed])

	#
	PART_SUFFIX=.0
	if [ -n "$PART_ROOT1" ]; then
		# Sleep a bit and hope kernel async console output passed by then
		[ -z "$slept" ] && $bb sleep 3
		slept=y

		while :; do
			echo
			echo '. Multiple $PART_ROOT[/$ROOT_DECRYPT] encountered:'
			echo "  [0] PART_ROOT=$PART_ROOT"
			[ -n "$ROOT_DECRYPT" ] && echo "  ROOT_DECRYPT=$ROOT_DECRYPT"
			ri=1
			while :; do
				eval rx="\$PART_ROOT$ri"
				[ -z "$rx" ] && break
				echo "  [$ri] ..ROOT$ri=$rx"
				eval rx="\$ROOT_DECRYPT$ri"
				[ -n "$rx" ] && echo "  ..CRYPT$ri=$rx"
				ri=$((ri + 1))
			done

			rmsg= rrt=
			if (echo y | read -t 1 chck) >/dev/null 2>&1; then
				rmsg=' (10 seconds until, or empty input for default)'
				rrt='-t 10'
			fi

			printf '. Please choose $PART_ROOT'"$rmsg"'? '
			read $rrt PART_SUFFIX
			if [ $? -ne 0 ] || [ -z "$PART_SUFFIX" ] || [ "$PART_SUFFIX" = 0 ]; then
				PART_SUFFIX=.0
				echo
				break
			elif [ "${PART_SUFFIX##*[^0-9]}" != "$PART_SUFFIX" ]; then
				echo >&2 '! Invalid input'
				continue
			fi

			eval ri=\$PART_ROOT$PART_SUFFIX
			if [ -z "$ri" ]; then
				echo >&2 '! No such PART_ROOT: '$PART_SUFFIX
			else
				PART_ROOT=$ri
				eval ROOT_DECRYPT=\$ROOT_DECRYPT$PART_SUFFIX
				PART_SUFFIX=.$PART_SUFFIX
				echo
				break
			fi
		done
	fi

	#
	if [ -n "$ROOT_DECRYPT" ]; then
		[ -z "$slept" ] && $bb sleep 3
		slept=y
		while :; do
			printf '. Please set free $PART_ROOT: '
			$bb stty -echo
			read ROOT_PASS
			$bb stty echo

			printf "%s" "$ROOT_PASS" | $cs open $PART_ROOT p_root --key-file - && break
			xconfirm 'Cannot cryptsetup open '"$PART_ROOT"', try again' || x 1
		done

		$bb mount $ROOT_DECRYPT /dev/mapper/p_root mnt || x 2

		if [ -n "$INIT_S2" ]; then
			echo '. Going $INIT_S2='"$INIT_S2"
			cd mnt || x 3

			boot/$BB mount --bind ../dev dev || x 10
			boot/$BB mount --bind ../sys sys || x 11
			boot/$BB mount --bind ../proc proc || x 12
			boot/$BB mount --bind ../run run || x 13

			exec boot/$BB chroot . /boot/$BB sh \
					/boot/linux-init-s2.sh --stage1 "$INIT_S2" \
						"$PART_SUFFIX" "$PART_ROOT" \
						"$ROOT_DECRYPT" "$ROOT_PASS" ||
				x 'Cannot go $INIT_S2'
		fi
	else
		echo '. Mounting $PART_ROOT'
		$bb mount $PART_ROOT mnt || x 2
	fi

	xswap $bb $cs

	echo '. About to pivot_root'
	cd mnt || x 3
	bb=boot/$bb
	$bb pivot_root . $PIVOT_OLDROOT || x 4

	$bb mount -o move $PIVOT_OLDROOT/dev dev || x 10
	$bb mount -o move $PIVOT_OLDROOT/sys sys || x 11
	$bb mount -o move $PIVOT_OLDROOT/proc proc || x 12
	$bb mount -o move $PIVOT_OLDROOT/run run || x 13

	echo '. Going sbin/init'
	$bb stty isig
	exec $bb chroot . sbin/init || x 'Cannot sbin/init'
} # }}}

if [ $# -ne 0 ]; then
	. $($1 dirname "$0")/linux-init-lib.sh
	xsetup "$1" "$2"
else
	. $(./$BB dirname "$0")/linux-init-lib.sh
	xroot
fi
exit 127

# s-sht-mode

[-- Attachment #3: linux-init-s2.sh --]
[-- Type: application/x-sh, Size: 7186 bytes --]

#@ /linux-init-s2.sh, simple Linux init, optional stage 2, called from stage 1.
#@ Requires $BB, $CS, as below, and these funs, on EFI / as well as new /boot/.
#@
#@   #@ For kent, stage 2
#@
#@   [KERNEL_ID=ideapad] - if set, only $KERNEL_ID-*.efi kernels are examined
#@   PART_ROOT=/dev/nvme0n1p8
#@   ROOT_DECRYPT='-t btrfs -o defaults,subvol=/crux-3.6/kent/root'
#@   PART_SWAP=/dev/nvme0n1p6
#@   INITRD_PATH=boot/.s2.initrd
#@   SWITCH_ROOT=media/initrd
#@
#@ Alternatively call AS ROOT and FROM WITHIN directory that boots like
#@   sh linux-init-s2.sh PATH_TO_BUSYBOX PATH_TO_CRYPTSETUP
#@ for init purposes.

# Identical to stage 1.
: ${MDEV_RUN:=}
#: ${PART_ROOT:=} via stage 1
#: ${ROOT_DECRYPT:=} via stage 1 (ditto ROOT_PASS)
: ${PART_SWAP:=}
: ${SWAP_INPUT:=}

# If non-empty, we try to load the given initrd (relative to root) instead of
# newly creating it; also, we will try to save it there if we had to create it
# Will get PART_SUFFIX of chosen PART_ROOT/ROOT_DECRYPT tuple!
: ${INITRD_PATH:=}

# Further arguments when kexec(8)ing the new kernel
: ${KEXEC_ARGS:=}
	: ${KEXEC_EXE:=usr/sbin/kexec}

# Running in the kexec(8) kernel, we may apply some file comparisons.
# If set it is a list of space separated files which must exist in /boot as
# well as $FILE_CHECK_PARTITION (most likely the same as $SWITCH_ROOT), that is
# temporarily mounted if it is not yet.
# The files $BB, $CS, linux-init-{lib,s1}.sh are implied
: ${FILE_CHECK:=}
	: ${FILE_CHECK_PARTITION:=media/efi}
	: ${FILE_CHECK_MOUNT_ARGS:=-n -t vfat /dev/nvme0n1p1}

# Where we move old root to when doing switch_root(8)
: ${SWITCH_ROOT:=media/initrd}

BB=busybox.static
CS=cryptsetup.static

# -- >8 -- 8< --

xkexec() { # $1=config file; assumes we are in / and boot/ "has it" {{{
	conf=$1

	# Find the possible kernels to boot
	set -- boot/*.efi
	ki=1 kdef= knew=
	for k
	do
		if [ -n "$KERNEL_ID" ]; then
			[ "${k##*$KERNEL_ID-*.efi}" != "$k" ] || continue
		fi
		if [ "${k##*-new.efi}" = "$k" ] && [ "${k##*-old.efi}" = "$k" ] && [ "${k##*-stage1.efi}" = "$k" ]; then
			#[ -z "$kdef" ] && kdef=$k
			kdef=$k
		fi
		if [ -z "$knew" ] && [ "${k##*-new.efi}" != "$k" ]; then
			knew=$k
		fi
		eval k$ki=$k
		ki=$((ki + 1))
	done

	# Let user choose one
	trap 'x "Got signal"' INT QUIT TERM
	echo '+ trapping INT/QUIT/TERM to start a shell'

	k= k0=-
	while [ -z "$k" ]; do
		echo
		echo '. Available kernels:'
		echo '  [0] Edit $KEXEC_ARGS'
		kj=1
		while [ $kj -lt $ki ]; do
			eval echo "\"	[$kj] \$k$kj\""
			kj=$((kj + 1))
		done
		echo

		if [ -n "$knew" ] && xconfirm 'Use the new kernel ('"$knew"')?'; then
			k=$knew
		else
			kmsg= krt=
			if [ -n "$kdef" ] && (echo y | read -t 1 chck) >/dev/null 2>&1; then
				kmsg=' (10 seconds until, or empty input for '"$kdef"')'
				krt='-t 10'
			fi

			printf '. Please choose kernel'"$kmsg"'? '
			read $krt kx
			if [ $? -ne 0 ] || [ -z "$kx" ]; then
				echo
				k=$kdef
			elif [ "${kx##*[^0-9]}" != "$kx" ]; then
				echo >&2 '! Invalid input'
				continue
			fi

			eval k=\$k$kx
			if [ -z "$k" ]; then
				echo >&2 '! No such kernel'
			elif [ "$k" = - ]; then
				printf "%s\n" "$KEXEC_ARGS" > run/.kexec
				echo '# Only first line counts.	Care for quoting!  :wq' run/.kexec
				boot/$BB vi run/.kexec
				k=$KEXEC_ARGS
				read KEXEC_ARGS < run/.kexec
				boot/$BB rm -f run/.kexec
				xconfirm "New KEXEC_ARGS=$KEXEC_ARGS" || KEXEC_ARGS=$k
				k=
			fi
		fi
	done

	# Create or reuse a temporary initrd that contains the password
	if [ -n "$INITRD_PATH" ] && [ -f "$INITRD_PATH$PART_SUFFIX" ] &&
			boot/$BB cp "$INITRD_PATH$PART_SUFFIX" run/.initrd; then
		echo '. Reusing initrd '"$INITRD_PATH$PART_SUFFIX"
	else
		echo '. Creating initrd'

		boot/$BB mount -o remount,exec run

		(
			set -e
			boot/$BB mkdir run/x
			cd run/x

			( xsetup2 "../../boot/$BB" "../../boot/$CS" )
			e=$?
			[ $e -ne 0 ] && exit $e

			./$BB mknod dev/console c 5 1 # redundant

			echo "#!/$BB sh" > ./init
			./$BB cat "$conf" >> ./init
			echo "PART_ROOT='$PART_ROOT'" >> ./init
			echo "ROOT_DECRYPT='$ROOT_DECRYPT'" >> ./init
			echo "ROOT_PASS='$ROOT_PASS'" >> ./init
			echo '. /linux-init-s2.sh' >> ./init
			./$BB chmod 0755 ./init

			{
				# Microcode update must be uncompressed and first
				[ -f ../../boot/early-ucode.cpio ] && ./$BB cat ../../boot/early-ucode.cpio
				# Followed by (possibly compressed) normal initrd
				./$BB find . | ./$BB cpio -H newc -o | ./$BB gzip -9 -n
			} > ../.initrd
		) || x 'Failed to create run/.initrd'

		boot/$BB mount -o remount,noexec run

		if [ -n "$INITRD_PATH" ]; then
			echo '. Saving initrd to '"$INITRD_PATH$PART_SUFFIX"
			boot/$BB cp run/.initrd "$INITRD_PATH$PART_SUFFIX"
			boot/$BB chmod 0600 "$INITRD_PATH$PART_SUFFIX"
		fi
	fi

	KEXEC_ARGS="$KEXEC_ARGS --initrd=run/.initrd"

	echo ". $KEXEC_EXE -l $k $KEXEC_ARGS"
	eval $KEXEC_EXE -l $k $KEXEC_ARGS || x 'Cannot invoke '"$KEXEC_EXE"' -l'
	echo ". $KEXE_EXE -e"
	exec $KEXEC_EXE -e || x 'Cannot invoke '"$KEXEC_EXE"' -e'
} # }}}

xfilecheck() { # $1=$BB; assumes we are in /mnt (_next_ root) {{{
	[ -z "$FILE_CHECK" ] && return
	echo '. Checking file equalities'

	umountpart=
	if xhavemnt "$1" "$FILE_CHECK_PARTITION"; then :; else
		umountpart=y
		$1 mount $FILE_CHECK_MOUNT_ARGS "$FILE_CHECK_PARTITION" || x 'Cannot mount '"$FILE_CHECK_PARTITION"
	fi

	err=
	$1 cmp -s "$1" "$FILE_CHECK_PARTITION"/$BB || err="$BB"
	$1 cmp -s boot/$CS "$FILE_CHECK_PARTITION"/$CS || err="$err $CS"
	$1 cmp -s boot/linux-init-lib.sh "$FILE_CHECK_PARTITION"/linux-init-lib.sh || err="$err init-lib.sh"
	$1 cmp -s boot/linux-init-s1.sh "$FILE_CHECK_PARTITION"/linux-init-s1.sh || err="$err init-s1.sh"

	if [ -f boot/early-ucode.cpio ] && [ -f "$FILE_CHECK_PARTITION"/early-ucode.cpio ]; then
		$1 cmp -s boot/early-ucode.cpio "$FILE_CHECK_PARTITION"/early-ucode.cpio || err="$err early-ucode.cpio"
	fi

	for f in $FILE_CHECK; do
		if [ -f "boot/$f" ] && [ -f "$FILE_CHECK_PARTITION/$f" ]; then
			$1 cmp -s "boot/$f" "$FILE_CHECK_PARTITION/$f" || err="$err $f"
		else
			err="$err (MISS: $f)"
		fi
	done

	[ -n "$umountpart" ] && $1 umount "$FILE_CHECK_PARTITION"

	if [ -z "$err" ]; then
		echo '  . Files successfully checked'
	else
		echo >&2 '! BOOT: $FILE_CHECK errors: '$err
		echo '! BOOT: $FILE_CHECK errors: '$err >> etc/motd
		$1 sleep 10
	fi
} # }}}

xroot() { # {{{
	# On initrd rootfs
	bb=./$BB cs=./$CS

	xbase_mounts "$bb"

	echo '. Setting free $PART_ROOT'
	printf "%s" "$ROOT_PASS" | $cs open $PART_ROOT p_root --key-file - || x 'Cannot cryptsetup open '"$PART_ROOT"

	$bb mount $ROOT_DECRYPT /dev/mapper/p_root mnt || x 2

	bb=mnt/boot/$BB
	cs=mnt/boot/$CS

	xswap $bb $cs

	cd mnt || x 3
	bb=boot/$BB
	cs=boot/$CS

	xfilecheck $bb

	echo '. Going switch_root sbin/init'
	$bb stty isig
	# -c dev/console
	exec $bb switch_root . sbin/init 2>&1 || x 'Cannot switch_root'
} # }}}

if [ "$1" = --stage1 ]; then
	cnf=$2
	PART_SUFFIX=$3
	PART_ROOT=$4
	ROOT_DECRYPT=$5
	ROOT_PASS=$6

	[ -f "$cnf" ] || x 'Cannot find $INIT_S2: '"$cnf"
	. "$cnf"
	. /boot/linux-init-lib.sh
	xkexec "$cnf"
elif [ $# -eq 2 ]; then
	. $($1 dirname "$0")/linux-init-lib.sh
	xsetup2 "$1" "$2" -
else
	. /linux-init-lib.sh
	xroot
fi
exit 127

# s-sht-mode

[-- Attachment #4: linux-init-lib.sh --]
[-- Type: application/x-sh, Size: 3646 bytes --]

#@ linux-init-lib.sh, helpers for simple init stage 1 and 2; will be sourced.

# misc {{{
x() {
	echo >&2 'ERROR ('"$*"')! Going shell'
	[ -x ./$BB ] && exec ./$BB sh
	[ -x /$BB ] && exec /$BB sh
	[ -x /boot/$BB ] && exec /boot/$BB sh
	[ -x /bin/sh ] && exec /bin/sh
	exit 100
}

xconfirm() {
	printf -- '. '"$*"' [Yy/else]? '
	read answer
	case $answer in
	[Yy]*) return 0;;
	*) return 1;;
	esac
}

_mpx= _mp=
xhavemnt() { # $1=$BB $2=file
	if [ "$2" = dev ]; then
		[ -e /dev/console ] && [ -e /dev/null ] && [ -e /dev/zero ]
		return $?
	elif [ "$2" = proc ]; then
		[ -e /proc/1 ] && [ -e /proc/self ] && [ -e /proc/uptime ]
		return $?
	elif [ "$2" = sys ]; then
		[ -e /sys/kernel ] && [ -e /sys/block ] && [ -e /sys/fs ]
		return $?
	fi

	if [ -z "$_mpx" ]; then
		_mpx=y
		$1 mountpoint -q / >/dev/null 2>&1 && _mp=y
	fi

	if [ -n "$_mp" ]; then
		$1 mountpoint -q "$2" >/dev/null 2>&1
		return $?
	elif [ -f /proc/mounts ]; then
		$1 grep -q ' '"$2"' ' /proc/mounts >/dev/null 2>&1
		return $?
	fi
	return 1
}

_xrand=
xrand() {
	_xrand=$(( (($RANDOM << 20) | ($RANDOM << 10) | ($RANDOM % 0x3FF)) ^ \
			(($RANDOM << 20) | ($RANDOM << 10) | ($RANDOM % 0x3FF))))
}
# }}}

xbase_mounts() { # {{{ $1=$BB [uses $MDEV_RUN; calls stty -isig]
	echo '. Checking /{dev,sys,proc,run}'

	xhavemnt $1 dev || $1 mount -n -t devtmpfs -o mode=0755,exec,nosuid,noatime none dev
	xhavemnt $1 sys || $1 mount -n -t sysfs none sys
	xhavemnt $1 proc || $1 mount -n -t proc none proc
	xhavemnt $1 run || $1 mount -n -t tmpfs -o mode=0755,noexec,nosuid,nodev none run

	#[ -e /sys/firmware/efi ] &&
	#mount -t efivarfs efivarfs /sys/firmware/efi/efivars -o nosuid,nodev,noexec

	$1 stty -isig

	if [ -n "$MDEV_RUN" ]; then
		echo '. About to run mdev -s, waiting for some more settlement'
		$1 sleep 8
		$1 mdev -s $MDEV_RUN
	fi
} # }}}

xsetup_base() { # $1=$BB $2=$CS [$3=no mdev stuff if set] {{{
	$1 cp -f "$1" ./$BB
	./$BB chmod 0700 ./$BB

	./$BB cp -f "$2" ./$CS
	./$BB chmod 0700 ./$CS

	./$BB cp -f "$0" .
	./$BB cp -f $(./$BB dirname "$0")/linux-init-lib.sh ./linux-init-lib.sh

	if [ $# -ne 3 ]; then
		# Prepare for $MDEV_RUN, too!
		./$BB mkdir etc bin dev mnt proc run sys $mdir

		./$BB cp ./$BB bin/sh
		./$BB chmod 0700 bin/sh

		echo ".* 0:0 660 @/$BB sh /etc/mdev.sh" > etc/mdev.conf
		./$BB cat > etc/mdev.sh <<-_EOT
			#@ /etc/mdev.sh for ./mdev.conf
			
			run() {
				if [ "\$ACTION" = add ]; then
					case "\$SUBSYSTEM" in
					block) block;;
					*) ;;
					esac
				fi
			
				exit
			}
			
			block() {
				[ -n "\$MDEV" ] || return
			
				[ -d /dev/disk ] || /$BB mkdir -p /dev/disk/by-uuid
			
				uuid=\$(/$BB blkid "\$MDEV" \| /$BB sed -Ee "s/.*UUID=\"([^\"]+)\".*/\1/")
				[ -n "\$uuid" ] || return
			
				/$BB ln -s ../../"\$MDEV" /dev/disk/by-uuid/"\$uuid"
			}
			
			run
		_EOT

		./$BB chmod 0700 etc/mdev.sh
	fi

	echo '! Plus kernel, init=SCRIPT, to be placed here'
}

xsetup() {
	xsetup_base "$@"
	exit
}

xsetup2() {
	xsetup_base "$@"
	# For $FILE_CHECK
	./$BB cp -f $(./$BB dirname "$0")/linux-init-s1.sh ./linux-init-s1.sh
	exit
} # }}}

xswap() { # $1=$BB $2=$CS {{{
	[ -z "$PART_SWAP" ] && return
	echo '. Encrypted swap'

	rand=
	if [ -n "$SWAP_INPUT" ]; then
		echo '  ... please type a line of randoms'
		$1 stty -echo >/dev/null 2>&1
		read rand
		$1 stty echo >/dev/null 2>&1
	else
		xrand
		rand=$_xrand
	fi

	xrand
	xr1=$_xrand
	xrand
	xr2=$_xrand
	xrand
	xr3=$_xrand
	xrand
	xr4=$_xrand
	xrand
	xr5=$_xrand

	echo "$xr1$rand$xr2$xr3$rand$xr4$xr5" |
			$2 open --type plain --cipher aes --key-size 256 --hash sha256 $PART_SWAP p_swap --key-file - &&
		$1 mkswap /dev/mapper/p_swap
} # }}}

# s-sht-mode

  reply	other threads:[~2023-09-10  1:23 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-04 14:44 [TUHS] " Norman Wilson
2023-09-04 14:55 ` [TUHS] " Vincenzo Nicosia
2023-09-04 17:20   ` Warner Losh
2023-09-04 19:05     ` Clem Cole
2023-09-05 17:03       ` Paul Winalski
2023-09-05 18:02         ` Clem Cole
2023-09-04 19:59     ` Theodore Ts'o
2023-09-04 23:51       ` Warner Losh
2023-09-04 17:18 ` Warner Losh
2023-09-04 22:10 ` Steffen Nurpmeso
2023-09-05 15:53   ` Steffen Nurpmeso
2023-09-06 17:50     ` Warner Losh
2023-09-07  0:11       ` Steffen Nurpmeso
2023-09-07 16:05         ` Warner Losh
2023-09-08 14:58           ` Theodore Ts'o
2023-09-08 13:56     ` Michael Kjörling
2023-09-08 23:38       ` Steffen Nurpmeso
2023-09-09 22:43         ` Steffen Nurpmeso [this message]
2023-09-11  4:10         ` Theodore Ts'o
2023-09-11 22:05           ` Steffen Nurpmeso
2023-09-05  1:07 ` Jonathan Gray
  -- strict thread matches above, loose matches on Subject: below --
2023-09-04  9:57 [TUHS] " Paul Ruizendaal via TUHS
2023-09-04 14:53 ` [TUHS] " emanuel stiebler
2023-09-04 17:07 ` Warner Losh
2023-09-04 18:21   ` Dan Cross
2023-09-05 11:15   ` Paul Ruizendaal via TUHS
2023-09-05 14:15     ` Clem Cole
2023-09-05 17:03     ` Warner Losh

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230909224312.gGToQ%steffen@sdaoden.eu \
    --to=steffen@sdaoden.eu \
    --cc=e5655f30a07f@ewoof.net \
    --cc=tuhs@tuhs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).