From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 23601 invoked from network); 10 Sep 2023 01:23:26 -0000 Received: from minnie.tuhs.org (50.116.15.146) by inbox.vuxu.org with ESMTPUTF8; 10 Sep 2023 01:23:26 -0000 Received: from minnie.tuhs.org (localhost [IPv6:::1]) by minnie.tuhs.org (Postfix) with ESMTP id 305D8402CE; Sun, 10 Sep 2023 11:23:19 +1000 (AEST) Received: from sdaoden.eu (sdaoden.eu [217.144.132.164]) by minnie.tuhs.org (Postfix) with ESMTPS id CDB9540120 for ; Sun, 10 Sep 2023 11:23:05 +1000 (AEST) Date: Sun, 10 Sep 2023 00:43:12 +0200 Author: Steffen Nurpmeso From: Steffen Nurpmeso To: Michael =?utf-8?Q?Kj=C3=B6rling?= Message-ID: <20230909224312.gGToQ%steffen@sdaoden.eu> In-Reply-To: <20230908233854.Xni_j%steffen@sdaoden.eu> References: <9A989054DE79CE5059CBA74797391E39.for-standards-violators@oclsc.org> <20230904221059.sF2G0%steffen@sdaoden.eu> <20230905155301.mIziN%steffen@sdaoden.eu> <20230908233854.Xni_j%steffen@sdaoden.eu> Mail-Followup-To: Michael =?utf-8?Q?Kj=C3=B6rling?= , tuhs@tuhs.org User-Agent: s-nail v14.9.24-507-g0e7e3e8c46 OpenPGP: id=EE19E1C1F2F7054F8D3954D8308964B51883A0DD; url=https://ftp.sdaoden.eu/steffen.asc; preference=signencrypt BlahBlahBlah: Any stupid boy can crush a beetle. But all the professors in the world can make no bugs. MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=jygCa7O9zwHRZJ2nZFVA-jIZp7rmIij31M6c=-=" Message-ID-Hash: CPE6FHDKCXP5XQUOVQT5ZFJ6RQXYP3AF X-Message-ID-Hash: CPE6FHDKCXP5XQUOVQT5ZFJ6RQXYP3AF X-MailFrom: steffen@sdaoden.eu X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: tuhs@tuhs.org X-Mailman-Version: 3.3.6b1 Precedence: list Subject: [TUHS] Re: Unix install & "standalone" package List-Id: The Unix Heritage Society mailing list Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This is a multi-part message in MIME format. --=-=jygCa7O9zwHRZJ2nZFVA-jIZp7rmIij31M6c=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Content-ID: <20230909224312.rux7u%steffen@sdaoden.eu> Steffen Nurpmeso wrote in <20230908233854.Xni_j%steffen@sdaoden.eu>: |Michael Kj=C3=B6rling wrote in | : ||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=3Dy CONFIG_KEXEC_FILE=3Dy CONFIG_ARCH_HAS_KEXEC_PURGATORY=3Dy # CONFIG_KEXEC_SIG is not set CONFIG_KEXEC_CORE=3Dy -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=3D/dev/nvme0n1p? ROOT_DECRYPT=3D'-t btrfs -o defaults,subvol=3D/crux/kent/root' PART_ROOT1=3D/dev/nvme0n1p8 ROOT_DECRYPT1=3D'-t btrfs -o defaults,subvol=3D/crux/kent/root.old' INIT_S2=3D/boot/kent-2.sh . /linux-init-s1.sh #?0|kent:/boot# v kent-2.sh #@ kent, stage 2 KERNEL_ID=3Dideapad ^ restrict kernel selection for kexec: ^ [ "${k##*$KERNEL_ID-*.efi}" !=3D "$k" ] || continue PART_SWAP=3D/dev/nvme0n1p6 SWAP_INPUT=3Dy ^ you can have additional interactive random for swap encryption ^ (it is a lie i use that in practice) INITRD_PATH=3D/boot/.kent.initrd KEXEC_ARGS=3D"--append=3D\"rtw88_pci.disable_aspm=3D1 rc.hostname=3Dkent\= "" FILE_CHECK=3D'kent-direct.sh kent.sh ideapad-stage1.efi' SWITCH_ROOT=3Dmedia/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=3D/dev/nvme0n1p8 ROOT_DECRYPT=3D'-t btrfs -o defaults,subvol=3D/crux/kent/root' PART_ROOT1=3D/dev/nvme0n1p8 ROOT_DECRYPT1=3D'-t btrfs -o defaults,subvol=3D/crux/kent/root.old' PART_SWAP=3D/dev/nvme0n1p6 PIVOT_OLDROOT=3Dmedia/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=3D/dev/nvme0n1p1 maxno=3D1 b1=3D0x01 L1=3Dkent l1=3Dideapad-stage1 u1=3D'root=3D'${d}' rootfstype=3Dvfat init=3D/kent.sh' driven by /root/bin/efiboot.sh (shortened): #!/bin/sh : ${HOSTNAME:=3D$(uname -n)} : ${DBG:=3D} if [ -f /root/hosts/${HOSTNAME}/efiboot ]; then . /root/hosts/${HOSTNAME}/efiboot else echo >&2 "MISS /root/hosts/${HOSTNAME}/efiboot" exit 1 fi if [ "$1" =3D create ]; then obo=3D$(efibootmgr | grep -E ^BootOrder: | sed -E 's/^BootOrder:[= [:space:]]*//') if [ -z "$obo" ]; then echo >&2 'Cannot determine previous boot order' exit 1 fi nbo=3D i=3D1 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=3D$nbo, eval nbo=3D\$nbo\$b$i i=3D$((i + 1)) done ${DBG} efibootmgr -o $nbo,$obo #> /dev/null elif [ "$1" =3D delete ]; then i=3D1 while [ $i -le $maxno ]; do eval ${DBG} efibootmgr -B -b \$b$i #>/dev/null i=3D$((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) --=-=jygCa7O9zwHRZJ2nZFVA-jIZp7rmIij31M6c=-= Content-Type: application/x-sh; charset=us-ascii Content-Disposition: attachment; filename="linux-init-s1.sh" Content-ID: <20230909224312.fj3JZ%steffen@sdaoden.eu> #@ /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 --=-=jygCa7O9zwHRZJ2nZFVA-jIZp7rmIij31M6c=-= Content-Type: application/x-sh; charset=us-ascii Content-Disposition: attachment; filename="linux-init-s2.sh" Content-ID: <20230909224312.wYbus%steffen@sdaoden.eu> #@ /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 --=-=jygCa7O9zwHRZJ2nZFVA-jIZp7rmIij31M6c=-= Content-Type: application/x-sh; charset=us-ascii Content-Disposition: attachment; filename="linux-init-lib.sh" Content-ID: <20230909224312.EGAFZ%steffen@sdaoden.eu> #@ 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 --=-=jygCa7O9zwHRZJ2nZFVA-jIZp7rmIij31M6c=-=--