#!/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 udevd udevadm mount modprobe umount $binaries" # structure for d in dev 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" 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 # TODO implement busybox mdev/mdevd # install mdev #mkdir "$tmpdir/usr/lib/mdev" #cp ./mdev/mdev.conf ./mdev/passwd ./mdev/group "$tmpdir/etc" #cp ./mdev/usbdev ./mdev/usbdisk_link ./mdev/ide_links "$tmpdir/usr/lib/mdev" #chmod +x $tmpdir/usr/lib/mdev/* # install udev find "/usr/lib/udev" -type f | grep -v "rc_keymaps\|hwdb.d" | cpio -pd "$tmpdir" #cat < "$tmpdir/etc/group" #root:x:0: #tty:x:5: #dialout:x:11: #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::/dev/null:/bin/false #EOF # handle lvm if [ "$use_lvm" = 1 ] && [ -x "$(command -v lvm)" ]; then binaries="lvm dmsetup $binaries" mkdir "$tmpdir/etc/lvm" # avoid lvmetad warning message echo "use_lvmetad = 0" >> "$tmpdir/etc/lvm/lvm.conf" if [ "$lvm_discard" = 1 ]; then echo "issue_discards = 1" >> "$tmpdir/etc/lvm/lvm.conf" fi # TODO implement use_lvmconf fi # handle luks if [ "$use_luks" = 1 ] && [ -x "$(command -v cryptsetup)" ]; then binaries="cryptsetup dmsetup $binaries" # avoid locking directory missing warning message mkdir "$tmpdir/run/cryptsetup" # TODO get rid of this workaround # workaround for luks2 cp "$(readlink -f libgcc_s.so.1)" "$tmpdir/usr/lib" cp -a /usr/lib/libgcc_s.so.1 "$tmpdir/usr/lib" if [ "$luks_discard" = 1 ]; then luks_args="--allow-discards $luks_args" fi # 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/usr/lib/$(readlink $l)" ]; then # regular cp "$(readlink -f $l)" "$tmpdir/usr/lib" strip -s "$tmpdir/usr/lib/$(readlink $l)" # 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" #drivers="$drivers" use_lvm="$use_lvm" lvm_discard="$lvm_discard" use_luks="$use_luks" luks_root="$luks_root" luks_header="$luks_header" luks_keyfile="$luks_keyfile" luks_discard="$luks_discard" 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"