#!/bin/sh # # tiny initramfs generation tool # debugging set -x # check root and files if [ "$(id -u)" != 0 ]; then echo "must be run as root" exit 1 elif [ ! -e ./config ]; then echo "config doesn't exists" exit 1 elif [ ! -e ./init ]; then echo "init doesn't exists" exit 1 # TODO remove static busybox dependency | handle busybox requirements ( busybox --list | grep ash ) elif [ ! -n "$(ldd ./busybox | grep "not a dynamic executable")" ]; then echo "busybox doesn't exists or dynamically linked. please download or/and build static busybox" exit 1 fi # source config . ./config # variables tmpdir="$(mktemp -d /tmp/initramfs.XXXXXXXX)" kernel="$(uname -r)" moddir="/lib/modules" binaries="./busybox findfs blkid mount modprobe umount $binaries" # structure for d in dev tmp var run etc usr/lib usr/bin mnt/root proc root sys; do mkdir -p "$tmpdir/$d" done # symlinks ( cd "$tmpdir" && { ln -s usr/lib lib ln -s usr/lib lib64 ln -s usr/bin bin ln -s usr/bin sbin ln -s ../run var/run cd "$tmpdir/usr" ln -s bin sbin ln -s lib lib64 } ) # TODO parse fstab | crypttab #while [ "$use_fstab" -eq 1 ] && read fs dir type opts; do thing; done < /etc/fstab # handle device managers if [ "$use_mdevd" = 1 ]; then # install mdevd binaries="mdevd mdevd-coldplug $binaries" mkdir "$tmpdir/lib/mdev" cp mdev.conf "$tmpdir/etc" cp storage-device "$tmpdir/lib/mdev" chmod +x "$tmpdir/lib/mdev/storage-device" elif [ "$use_mdev" = 1 ]; then # install mdev mkdir "$tmpdir/lib/mdev" cp mdev.conf "$tmpdir/etc" cp storage-device "$tmpdir/lib/mdev" chmod +x "$tmpdir/lib/mdev/storage-device" elif [ "$use_udev" = 1 ]; then # install udev binaries="udevd udevadm dmsetup $binaries" find /usr/lib/udev -type f | grep -v "rc_keymaps\|hwdb.d" | cpio -pd "$tmpdir" fi cat < "$tmpdir/etc/group" root:x:0: tty:x:5: dialout:x:11: uucp:x:14: kmem:x:3: input:x:25: video:x:13: audio:x:12: lp:x:10: disk:x:9: cdrom:x:16: tape:x:6: kvm:x:24: floppy:x:8: EOF cat < "$tmpdir/etc/passwd" root:x:0:0::/root:/bin/sh nobody:x:99:99::/:/bin/false EOF # handle lvm if [ "$use_lvm" = 1 ] && [ -x "$(command -v lvm)" ]; then binaries="lvm $binaries" #mkdir "$tmpdir/etc/lvm" # use_lvmetad = 0 - avoid lvmetad missing warning message #cat < "$tmpdir/etc/lvm/lvmlocal.conf" #local { # issue_discards = ${lvm_discard:-0} # use_lvmetad = 0 #} #EOF # TODO implement use_lvmconf fi # handle luks if [ "$use_luks" = 1 ] && [ -x "$(command -v cryptsetup)" ]; then binaries="cryptsetup $binaries" # avoid locking directory missing warning message mkdir "$tmpdir/run/cryptsetup" # TODO get rid of this workaround # workaround for luks2 cp /usr/lib/libgcc_s.so.1 "$tmpdir/usr/lib" [ "$luks_discard" = 1 ] && luks_args="--allow-discards $luks_args" # TODO detached header # TODO keyfile fi # TODO rewrite drivers installing | handle $drivers config var # install drivers find \ "$moddir/$kernel/kernel/drivers/virtio" \ "$moddir/$kernel/kernel/arch" \ "$moddir/$kernel/kernel/crypto" \ "$moddir/$kernel/kernel/fs" \ "$moddir/$kernel/kernel/lib" \ "$moddir/$kernel/kernel/drivers/block" \ "$moddir/$kernel/kernel/drivers/ata" \ "$moddir/$kernel/kernel/drivers/md" \ "$moddir/$kernel/kernel/drivers/scsi" \ "$moddir/$kernel/kernel/drivers/usb/storage" \ "$moddir/$kernel/kernel/drivers/usb/host" \ -type f | cpio -pd "$tmpdir" 2>/dev/null # install list of drivers cp "$moddir/$kernel/modules.softdep" "$moddir/$kernel/modules.builtin" "$moddir/$kernel/modules.order" "$tmpdir/$moddir/$kernel" # generate dependencies list of drivers depmod -b "$tmpdir" "$kernel" # TODO make strip optional # install and strip binaries and libraries for b in $(echo $binaries); do # check binary existence if [ ! "$(command -v $b)" ]; then echo "$b doesn't exists or permission denied" exit 1 fi # copy and strip binary cp "$(command -v $b)" "$tmpdir/usr/bin" chmod +x "$tmpdir/usr/bin/$b" strip -s "$tmpdir/usr/bin/$b" # check statically linking ldd "$(command -v $b)" >/dev/null || continue # handle libraries symlinks for dymanically linked binaries for l in $(ldd "$(command -v $b)" | sed -nre 's,.* (/.*lib.*/.*.so.*) .*,\1,p' -e 's,.*(/lib.*/ld.*.so.*) .*,\1,p'); do # check symlink if [ -h "$l" ]; then # check lib already existence if [ ! -e "$tmpdir/usr/lib/${l##*/}" ] && [ ! -e "$tmpdir$(readlink -f $l)" ]; then # regular cp "$(readlink -f $l)" "$tmpdir/usr/lib" strip -s "$tmpdir$(readlink -f $l)" # TODO handle all symlinks # symlink may link to symlink [ -h "/usr/lib/$(readlink $l)" ] && cp -a "/usr/lib/$(readlink $l)" "$tmpdir/usr/lib" # symlink cp -a "$l" "$tmpdir/usr/lib" fi else if [ ! -e "$tmpdir/usr/lib/${l##*/}" ]; then cp "$l" "$tmpdir/usr/lib" strip -s "$tmpdir/usr/lib/${l##*/}" fi fi done done # install init cp ./init "$tmpdir/init" chmod +x "$tmpdir/init" # initialize config cat < "$tmpdir/config" root="$root" root_type="$root_type" root_args="$root_args" use_mdevd="$use_mdevd" use_mdev="$use_mdev" use_udev="$use_udev" #drivers="$drivers" use_lvm="$use_lvm" use_luks="$use_luks" luks_root="$luks_root" luks_header="$luks_header" luks_keyfile="$luks_keyfile" luks_args="$luks_args" EOF # TODO add another compession tools # packing if ! ( cd "$tmpdir" && find . | cpio --create --verbose --format=newc | gzip --best ) > "./initramfs-$kernel.img.gz" 2>/dev/null; then echo "failed" exit 1 fi # remove tmpdir rm -rf "$tmpdir" echo "done! check out initramfs-$kernel.img.gz"