diff --git a/LICENSE b/LICENSE index dd3ba37..0d7fde0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,8 @@ -Minimal Linux Booter +Linux Live Framework +====================== -Copyright (C) 2023 Tomas M . -Copyright (C) 2023 Danuel K. . +Copyright (C) 2023 Tomas M. . +Copyright (C) 2023 Daniel K. . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,4 +17,4 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -MA 02110-1301 USA. \ No newline at end of file +MA 02110-1301 USA. diff --git a/README.txt b/README.txt index 07896af..cf0a3b3 100644 --- a/README.txt +++ b/README.txt @@ -1,7 +1,7 @@ -Minimal Linux Booter -==================== +Linux Live Framework +====================== -This project is to minimize Linux-Live Kit (https://github.com/Tomas-M/linux-live) +This project is for supporting many CPUs architectures & extended functions unlike Linux-Live Kit (https://github.com/Tomas-M/linux-live) Note: * Your distro must have installed: @@ -14,6 +14,7 @@ Note: - tar, - grep, - rsync, + - find-utils, - syslinux-utils, - bash, - (Optional) mdadm. diff --git a/build b/build index 768291e..9c5f21f 100755 --- a/build +++ b/build @@ -1,53 +1,35 @@ #!/usr/bin/env bash -for i in mksquashfs cpio gzip sed grep xorriso tar file; do +set -eE -o pipefail +exec > >(tee -i /tmp/lif.log) 2>&1 +cd "$(dirname $(readlink -f ${0}))" +cp -fv config .config +for i in mksquashfs cpio gzip sed grep xorriso tar find file; do if [ ! -x "$(command -v ${i})" ]; then case ${i} in mksquashfs) a="squashfs-tools";; readelf) a="binutils";; + find) a="find-utils";; *) a="${i}" esac echo "Please install ${a} package to run this tool" - exit 1 + false fi done - -exec > >(tee -i /tmp/mlb.log) 2>&1 -cd "$(dirname $(readlink -f ${0}))" || exit 1 -cp -f config .config - -mapfile -t list < <(ls -A /boot | egrep "bzImage|kernel|vmlinuz" 2>/dev/null | egrep -v "init|*.old") -if [ ${#list[@]} -gt 1 ]; then - n=0 - echo -e "Please choose your kernel to proceed:\nChoose number from ${n} to ${#list[@]}\n-----\n" - for a in "${list[@]}"; do - echo "[${n}] - ${a}" - ((n++)) - done - echo "-----" - read kernel - kernel="/boot/${list[${kernel}]}" - unset list n -else - kernel="/boot/${list[0]}" -fi -set -x -time ( - echo "KERNEL=\"${kernel}\"" >>.config +main() +{ + local top DATA INITRD ret tmpRoot utc v + echo "KERNEL=\"${kernel}}\"" >>.config echo "LMK=\"/lib/modules/$(file -bL ${kernel} | grep -o 'version .*' | cut -d' ' -f2)\"" >>.config - unset kernel top="$(pwd)" - . .config - workTmpDir="$(mktemp -d /tmp/Mlb_WorkDir_XXXXXXX)" DATA="${workTmpDir}/isoImage" INITRD="$(initrd/create)" ret="${?}" tmpRoot="${workTmpDir}/tmpRoot" - trap "rm -rf ${workTmpDir} /tmp/MlbInitRd{,.img}&&exit 1" 2 6 15 - mkdir -p ${DATA}/changes ${DATA}/${DISTRO}/modules + mkdir -pv ${DATA}/changes ${DATA}/os/modules rsync --force -aAP $(for i in $(awk '{print $2}' /proc/mounts) /tmp; do echo "--exclude=${i}/*"; done) / ${tmpRoot} - chmod +x -R inc2sys - cp -rf inc2sys/* ${tmpRoot} + chmod +x -Rv inc2sys + cp -rvf inc2sys/* ${tmpRoot} mknod ${tmpRoot}/dev/console c 5 1 mknod ${tmpRoot}/dev/null c 1 3 mknod ${tmpRoot}/dev/ram0 b 1 0 @@ -56,27 +38,69 @@ time ( mknod ${tmpRoot}/dev/tty3 c 4 3 mknod ${tmpRoot}/dev/tty4 c 4 4 for i in zstd xz lzma bzip2 gzip; do - mksquashfs ${tmpRoot} ${DATA}/${DISTRO}/system.sfs -comp ${i} -noappend -limit 50 - [ -e ${DATA}/${DISTRO}/system.sfs ]&&break + mksquashfs ${tmpRoot} ${DATA}/os/system.sfs -comp ${i} -noappend -limit 50 + [ -e ${DATA}/os/system.sfs ]&&break done - mv -f ${INITRD} ${DATA}/initrd.img - cp -rf bootfiles/* ${DATA} + mv -fv ${INITRD} ${DATA}/initrd.img + cp -rvf bootfiles/* ${DATA} for i in ${DATA}/syslinux.cfg ${DATA}/boot/grub/grub.cfg; do sed -i -r "s/__DISTRO__/${DISTRO}/" ${i} done cp -f ${KERNEL} ${DATA}/vmlinuz cd ${DATA} utc="$(date +%s)" - v="$(git -C ${top} rev-parse HEAD 2>/dev/null)"&&v="${v}:GIT"||v="INFINITY:LOCAL" - cat <.MlbMeta -# Built using Minimal-Linux-Booter technology. -MLB_VERSION="${v}" -MLB_NAME="${DISTRO}" -MLB_UTC="${utc}" + v="$(git -C ${top} rev-parse HEAD 2>/dev/null|tr [:lower:] [:upper:]):$(git -C ${top} branch --show-current 2>/dev/null|tr [:lower:] [:upper:]):GIT"||v="INFINITY:PRIVATE:LOCAL" + cat <.LlfMeta +# Built using Linux-Live-Framework technology. +LLF_VERSION="${v}" +LLF_NAME="${DISTRO}" +LLF_UTC="${utc}" eot - [[ ${ret} = 2 ]]&&echo "MLB_ELF_STATIC_INITRD=\"1\"" >>.MlbMeta||echo "MLB_ELF_STATIC_INITRD=\"0\"" >>.MlbMeta + [[ ${ret} = 2 ]]&&echo "LLF_ELF_STATIC_INITRD=\"y\"" >>.LlfMeta||echo "LLF_ELF_STATIC_INITRD=\"n\"" >>.LlfMeta xorriso -as mkisofs -o /${DISTRO}-${utc}.iso -iso-level 3 -J -R -D -A ${DISTRO} -V ${DISTRO} -no-emul-boot -boot-info-table -boot-load-size 2 -b boot/grub/i386-pc/eltorito.img -c boot/grub/grub.cat -eltorito-alt-boot -e /efi.img -no-emul-boot . isohybrid --version >/dev/null 2>&1&&isohybrid -u /${DISTRO}-${utc}.iso - cd ${top} - rm -rf ${workTmpDir} -) + return 0 +} +chooseKernel() +{ + local n=0 list + mapfile -t list < <(find /boot -type f | egrep "bzImage|kernel|vmlinuz" 2>/dev/null | egrep -v "init|*.old") + if [ ${#list[@]} -gt 1 ]; then + echo -e "Please choose your kernel to proceed:\nChoose number from ${n} to ${#list[@]}\n-----\n" + for a in "${list[@]}"; do + echo "[${n}] - ${a}" + ((n++)) + done + echo "-----" + read kernel + kernel="/boot/${list[${kernel}]}" + else + kernel="/boot/${list[0]}" + fi + export kernel + return 0 +} +for i; do + case ${i} in + -i|--interactive) helper="true" ;; + -k|--kernel) export kernel="${2}"; shift ;; + -d|--distro) DISTRO="${2}"; shift ;; + -w|--workdir) workTmpDir="${2}"; shift ;; + -D|--debug) set -x; export V="-v" ;; + -C|--clean) clean="true" ;; + --) shift; break ;; + *) echo "Unknown option: ${i}"; exit 1 ;; + esac +done +trap '[[ ${clean} ]]&&echo "Cleaning up..."&&rm -rvf ${workTmpDir} /tmp/MlbInitRd{,.img};exit 1' 2 6 15 +export workTmpDir +[[ -t 0 && ${helper} || ${helper} ]]&&if chooseKernel&&main; then true else; false; fi +[[ ! ${helper} ]]&& { + [[ ! -e ${kernel} ]]&&echo "[E]: Kernel not found: ${kernel}"&&false + [[ -z ${DISTRO} ]]&&. .config&&echo "[W]: DISTRO not set. Using defaults: ${DISTRO}"||true + [[ -z ${workTmpDir} ]]&&workTmpDir="$(mktemp -d /tmp/Llf_WorkDir_XXXXXXX)"&&echo "[W]: workTmpDir not set. Using defaults: ${workTmpDir}"&&true + export workTmpDir + export DISTRO + mkdir -pv "${workTmpDir}" + if main; then true; else false; fi +} diff --git a/inc2sys/usr/bin/install-linux b/inc2sys/usr/bin/install-linux index 82bb8ea..79ef424 100755 --- a/inc2sys/usr/bin/install-linux +++ b/inc2sys/usr/bin/install-linux @@ -8,7 +8,7 @@ # This shell script is contributed under the terms of GPL v2 by Thomas Schoenhuetl 22.05.2007. # Modified script "slax2hd" for installing Generic Linux to hdd -# BY: Daniel K. aka *DANiO* +# BY: Daniel K. aka Danieliskoto for i in dialog fdisk cfdisk sed grep mke2fs grub-install; do if [ ! -x $(command -v ${i}) ]; then diff --git a/initrd/create b/initrd/create index 2c425d2..5cb83c8 100755 --- a/initrd/create +++ b/initrd/create @@ -5,7 +5,7 @@ cd "$(dirname $(readlink -f ${0}))"||exit 1 . ../.config -INITRAMFS="/tmp/MlbInitRd" +INITRAMFS="/tmp/LifInitRd" trap "rm -rf ${INITRAMFS}&&exit 1" 2 3 6 15 # copy file to initramfs tree, including @@ -99,7 +99,7 @@ cp static/fsck $INITRAMFS/bin [[ ${static} ]]&&cp static/mdadm $INITRAMFS/bin||copy_including_deps /sbin/mdadm [[ ${static} ]]&&cp static/mount.ntfs-3g $INITRAMFS/bin||copy_including_deps /sbin/mount.ntfs-3g #[[ ${static} ]]&&cp static/blkid $INITRAMFS/bin||copy_including_deps /sbin/blkid -#copy_including_deps /usr/bin/eject || cp static/eject $INITRAMFS/bin +#[[ ${static} ]]&©_including_deps /usr/bin/eject || cp static/eject $INITRAMFS/bin # trim modules.order file. Perhaps we could remove it entirely MODULEORDER="$(cd "$INITRAMFS/$LMK/"; find -name "*.ko" | sed -r "s:^./::g" | tr "\n" "|" | sed -r "s:[.]:.:g")" diff --git a/initrd/functions b/initrd/functions index ace69b2..3ef106b 100755 --- a/initrd/functions +++ b/initrd/functions @@ -13,21 +13,21 @@ export SHELL_IS_ENABLED="_SHELL_ENABLED_" progress() { + local pid sh -c "${1}" >/dev/null 2>&1& - local pid="${!}" + pid="${!}" while :; do if [ -d /proc/${pid} ]; then echo -n "." sleep 0.25 else - echo -en " DONE!\n" break fi done } grepCmdLine() { - for i in `/dev/null 2>&1 return ${?} } +m() +{ + case "${1}" in + q) printf '%s' "[Question]: ${2}";; + a) printf '%s' "[Answer]: ${2}";; + A) printf '%s' "[Action]: ${2}";; + i) printf '%s' "[Info]: ${2}";; + w) printf '%s' "[Warning]: ${2}";; + e) printf '%s' "[Error]: ${2}";; + f) printf '%s' "[Fatal]: ${2}";; + *) printf '%s' "${1}";; + esac +} isShellEnabled() { - d&&echo -n "Is 'shell' bootloader variable set? " + d&&m q "Is 'shell' bootloader variable set " if grepCmdLine shell; then - d&&echo -en "Yes\n" + d&&m a "Yes\n" sed -i "s/_SHELL_ENABLED_/true/g" /lib/functions >/dev/null 2>&1 - echo "[!] Reloading /lib/functions" + m A "Reloading /lib/functions " if . /lib/functions; then - echo -en "Done\n" + m i "Done\n" else - echo -en "Failed\n" + m f "Failed\n" emergencyShell fi else - d&&echo -en "No\n" + d&&m a "No\n" fi } isZramEnabled() { - d&&echo -n "Is zram supported? " + d&&m q "Is zram supported? " if [ -e /sys/block/zram0/disksize ]; then - d&&echo -en "Yes\n" + d&&m a "Yes\n" + m A "Enabling zram " echo 536870912 >/sys/block/zram0/disksize - mkswap /dev/zram0 >/dev/null 2>&1 - swapon /dev/zram0 >/dev/null 2>&1 + mkswap /dev/zram0 >/dev/null 2>&1&&m i "Done\n"||m w "Failed\n" + swapon /dev/zram0 >/dev/null 2>&1&&m i "Done\n"||m w "Failed\n" echo 100 >/proc/sys/vm/swappiness else - d&&echo -en "No\n" + d&&m i "No\n" fi } findData() { - d&&echo -n "Searching ${DISTRO} in /dev -> " - #local from="$(grepCmdLine from)" + d&&m A "Searching ${DISTRO} in /dev -> " + local from a + from="$(grepCmdLine from)" for i in ${root:-/dev/[hmnsv][dmrv][0-9a-z]*}; do - d&&echo -n "${i#/dev/} " + d&&m "${i#/dev/} " mount -o ro ${i} ${DATAMNT} >/dev/null 2>&1 sleep 0.5 - #[[ ${from} ]]&&mount ${DATAMNT}/${from} ${DATAMNT} >/dev/null 2>&1 - if [ -e ${DATAMNT}/${DISTRO}/system.sfs ]; then - d&&echo -e "\nFound ${DISTRO} in ${i}" + [[ ${from} ]]&&mount ${DATAMNT}/${from} ${DATAMNT} >/dev/null 2>&1 + if [ -e ${DATAMNT}/.LlfMeta ]; then + d&&m i "\nFound ${DISTRO} in ${i}\n" grepCmdLine fsck&&fsck ${i} >/dev/null 2>&1||true - d&&echo -n "Is 'toram' bootloader variable set and enought RAM space? " - if grepCmdLine toram; local a=${?}&&[[ "$(grep MemFree /proc/meminfo|awk '{print $2}')" -gt $(("$(du ${DATAMNT}|tail -n1|awk '{print $1}')"-"$(du ${DATAMNT}/changes|tail -n1|awk '{print $1}')")) ]]; then - d&&echo -en "Yes\n" + d&&m q "Is 'toram' bootloader variable set and enought RAM space? " + if grepCmdLine toram; a=${?}&&[[ "$(grep MemFree /proc/meminfo|awk '{print $2}')" -gt $(("$(du ${DATAMNT}|tail -n1|awk '{print $1}')"-"$(du ${DATAMNT}/changes|tail -n1|awk '{print $1}')")) ]]; then + d&&m a "Yes\n" mkdir -p /tmp/data - d&&echo -n "Copying to RAM " - d&&progress "tar -c -C ${DATAMNT} --exclude ./changes -f - . | tar -xf - -C /tmp/data" + d&&m A "Copying to RAM " + d&&progress "tar -c -C ${DATAMNT} --exclude ./changes -f - . | tar -xf - -C /tmp/data"&&m i "Done\n"||m w "Failed\n" umount -f ${DATAMNT} >/dev/null 2>&1 - #[[ ${from} ]]&&umount -f ${DATAMNT} >/dev/null 2>&1 + [[ ${from} ]]&&umount -f ${DATAMNT} >/dev/null 2>&1 mv -f /tmp/data/* ${DATAMNT} >/dev/null 2>&1 rm -rf /tmp/data >/dev/null 2>&1 else - d&&if [[ "${a}" != "0" ]]; then echo -ne "Not requested by bootloader or low RAM space!\n"; else echo -ne "Internal error? Trying tmpfs, so data after power-off will be erased permanently!\n"; fi + d&&[[ "${a}" != "0" ]]&&m e "Not requested by bootloader or low RAM space!\n"||m e "Internal error? Trying tmpfs, so data after power-off will be erased permanently!\n" mount -o remount,rw ${DATAMNT} >/dev/null 2>&1||true fi - mount ${DATAMNT}/${DISTRO}/system.sfs ${SYSTEM} >/dev/null 2>&1 + mount ${DATAMNT}/os/system.sfs ${SYSTEM} >/dev/null 2>&1 sleep 0.5 break else @@ -99,22 +114,22 @@ findData() fi done if ! grep -q ${SYSTEM} /proc/mounts; then - d&&echo "Can not find compatible distro!" + d&&m f "Can not find compatible distro!\n" emergencyShell fi } findModules() { - d&&echo -n "Trying to mount modules from ${DATAMNT}/${DISTRO}/modules -> " + d&&m A "Trying to mount modules from ${DATAMNT}/${DISTRO}/modules -> " if ls ${DATAMNT}/${DISTRO}/modules/*.sfs >/dev/null 2>&1; then for i in $(find ${DATAMNT}/${DISTRO}/modules -maxdepth 1 -type f -name "*.sfs"|sort); do mkdir -p ${MODULES}/$(basename ${i} .sfs) - d&&echo -n "$(basename ${i}) " + d&&m "$(basename ${i}) " mount ${i} ${MODULES}/$(basename ${i} .sfs) >/dev/null 2>&1 done - d&&echo -en "Done\n" + d&&m i "Done\n" else - d&&echo -en "Failed, modules not found! Continuing...\n" + d&&m w "Modules not found! Continuing...\n" fi } mountOverlay() @@ -128,37 +143,33 @@ mountOverlay() persistentChanges() { if ! grepCmdLine perch&&grepCmdLine toram; then - return + return ${?} fi local CHANGES T1 T2 EXISTS CHANGES=$DATAMNT/changes T1="$CHANGES/.empty" T2="$T1"2 + d&&m A "Testing for RW access to persistent changes...\n" mkdir -p "$2" - touch "$T1" 2>/dev/null && rm -f "$T1" 2>/dev/null - if [ $? -ne 0 ]; then - return - fi - d&&echo "Testing persistent changes for posix compatibility" - touch "$T1" && ln -sf "$T1" "$T2" 2>/dev/null && \ - chmod +x "$T1" 2>/dev/null && test -x "$T1" && \ - chmod -x "$T1" 2>/dev/null && test ! -x "$T1" && \ - rm "$T1" "$T2" 2>/dev/null + touch "$T1" 2>/dev/null&&rm -f "$T1" 2>/dev/null||d&&m w "Failed\n" + d&&m A "Testing persistent changes for posix compatibility...\n" + touch "$T1"&&ln -sf "$T1" "$T2" 2>/dev/null&&chmod +x "$T1" 2>/dev/null&&test -x "$T1"&&chmod -x "$T1" 2>/dev/null&&test ! -x "$T1"&&rm "$T1" "$T2" 2>/dev/null if [ $? -eq 0 ]; then - d&&echo "Activating native persistent changes" + d&&m A "Activating native persistent changes\n" mount --bind "$CHANGES" "$2" >/dev/null 2>&1 - return + return ${?} + else + d&&m w "Failed\n" fi if [ -e "$CHANGES/changes.dat.0" ]; then - d&&echo "Restoring persistent changes" + d&&m A "Restoring persistent changes\n" EXISTS="true" else - d&&echo "Creating new persistent changes" - EXISTS="" + d&&m A "Creating new persistent changes\n" fi - mount.dynfilefs -f "$CHANGES/changes.dat" -s 16000 -m "$2" -p 4000 >/dev/null 2>&1 - [ ! "$EXISTS" ] && mke2fs -F -L "DATA" "$2/virtual.dat" >/dev/null 2>&1 - grepCmdLine fsck && fsck ${2}/virtual.dat >/dev/null 2>&1 + mount.dynfilefs -f "$CHANGES/changes.dat" -s 16000 -m "$2" -p 4000 >/dev/null 2>&1||d&&m e "Failed\n" + [ "$EXISTS" ]||mke2fs -F -L "DATA" "$2/virtual.dat" >/dev/null 2>&1 + grepCmdLine fsck&&fsck ${2}/virtual.dat >/dev/null 2>&1 mount "$2/virtual.dat" "$2" >/dev/null 2>&1 rm "$T1" "$T2" >/dev/null 2>&1 rmdir "$2/lost+found" >/dev/null 2>&1 @@ -170,6 +181,11 @@ debugShell() setsid cttyhack sh fi } +pivotRoot() +{ + pivot_root ${1} run/initramfs + exec chroot ${1} init +} changeRoot() { cd "$1" @@ -185,8 +201,7 @@ eot mount -t tmpfs tmpfs run mkdir -p run/initramfs mount -o remount,ro overlay . - pivot_root . run/initramfs - exec chroot . init + pivotRoot . } emergencyShell() { diff --git a/initrd/init b/initrd/init index 281f67c..34efd72 100755 --- a/initrd/init +++ b/initrd/init @@ -18,13 +18,13 @@ if [ ! -e /lib/.escaped ]; then fi mount -t devtmpfs devtmpfs /dev >/dev/null 2>&1 ln -sf /proc/self/fd /dev/fd -exec > >(tee -i /tmp/mlb.log) 2>&1 +exec > >(tee -i /tmp/lif.log) 2>&1 d&&echo "'debug' bootloader variable is set!"&&set -x mount -t sysfs sysfs /sys >/dev/null 2>&1 mkdir -p ${UNION} ${DATAMNT} ${SYSTEM} isShellEnabled ln -sf /proc/mounts /etc/mtab -find /lib/modules/`uname -r` -name "*.ko" -type f | sed -r "s:^.*/|[.]ko\$::g" | xargs -n 1 modprobe >/dev/null 2>&1 +find /lib/modules/$(uname -r) -name "*.ko" -type f | sed -r "s:^.*/|[.]ko\$::g" | xargs -n 1 modprobe >/dev/null 2>&1 sleep 3 mdev -s debugShell diff --git a/initrd/shutdown b/initrd/shutdown index 0381187..ac67071 100755 --- a/initrd/shutdown +++ b/initrd/shutdown @@ -19,8 +19,9 @@ umount_all() exec >/dev/console 2>>/dev/console [ "${DEBUG_IS_ENABLED}" = "true" ]&&set -x +read -sr -N 1 -t 5 -p "[Info]: If poweroff by accident, press any key to restore your work. Waiting 5 seconds for input..."&&pivotRoot /oldroot debugShell -echo "Minimal Linux Booter - Shutdown Magic!" +echo "Linux Live Framework - Shutdown Magic!" echo "Entering to clean-up things before final step." ( mdev -s