Lx4U-book/docs/scripts/mkinitramfs.sh
2021-11-04 19:24:31 +03:00

361 lines
9.3 KiB
Bash

cat > /sbin/mkinitramfs << "EOF"
#!/bin/bash
# This file based in part on the mkinitramfs script for the LFS LiveCD
# written by Alexander E. Patrakov and Jeremy Huntwork.
copy()
{
local file
if [ "$2" = "lib" ]; then
file=$(PATH=/lib:/usr/lib type -p $1)
else
file=$(type -p $1)
fi
if [ -n "$file" ] ; then
cp $file $WDIR/$2
else
echo "Missing required file: $1 for directory $2"
rm -rf $WDIR
exit 1
fi
}
if [ -z $1 ] ; then
INITRAMFS_FILE=initrd.img-no-kmods
else
KERNEL_VERSION=$1
INITRAMFS_FILE=initrd.img-$KERNEL_VERSION
fi
if [ -n "$KERNEL_VERSION" ] && [ ! -d "/lib/modules/$1" ] ; then
echo "No modules directory named $1"
exit 1
fi
mkdir -p /usr/share/mkinitramfs &&
cat > /usr/share/mkinitramfs/init.in << "EOF"
#!/bin/sh
PATH=/bin:/usr/bin:/sbin:/usr/sbin
export PATH
problem()
{
printf "Encountered a problem!\n\nDropping you to a shell.\n\n"
sh
}
no_device()
{
printf "The device %s, which is supposed to contain the\n" $1
printf "root file system, does not exist.\n"
printf "Please fix this problem and exit this shell.\n\n"
}
no_mount()
{
printf "Could not mount device %s\n" $1
printf "Sleeping forever. Please reboot and fix the kernel command line.\n\n"
printf "Maybe the device is formatted with an unsupported file system?\n\n"
printf "Or maybe filesystem type autodetection went wrong, in which case\n"
printf "you should add the rootfstype=... parameter to the kernel command line.\n\n"
printf "Available partitions:\n"
}
do_mount_root()
{
mkdir /.root
[ -n "$rootflags" ] && rootflags="$rootflags,"
rootflags="$rootflags$ro"
case "$root" in
/dev/* ) device=$root ;;
UUID=* ) eval $root; device="/dev/disk/by-uuid/$UUID" ;;
PARTUUID=*) eval $root; device="/dev/disk/by-partuuid/$PARTUUID" ;;
LABEL=* ) eval $root; device="/dev/disk/by-label/$LABEL" ;;
"" ) echo "No root device specified." ; problem ;;
esac
while [ ! -b "$device" ] ; do
no_device $device
problem
done
if ! mount -n -t "$rootfstype" -o "$rootflags" "$device" /.root ; then
no_mount $device
cat /proc/partitions
while true ; do sleep 10000 ; done
else
echo "Successfully mounted device $root"
fi
}
do_try_resume()
{
case "$resume" in
UUID=* ) eval $resume; resume="/dev/disk/by-uuid/$UUID" ;;
LABEL=*) eval $resume; resume="/dev/disk/by-label/$LABEL" ;;
esac
if $noresume || ! [ -b "$resume" ]; then return; fi
ls -lH "$resume" | ( read x x x x maj min x
echo -n ${maj%,}:$min > /sys/power/resume )
}
init=/sbin/init
root=
rootdelay=
rootfstype=auto
ro="ro"
rootflags=
device=
resume=
noresume=false
mount -n -t devtmpfs devtmpfs /dev
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
mount -n -t tmpfs tmpfs /run
read -r cmdline < /proc/cmdline
for param in $cmdline ; do
case $param in
init=* ) init=${param#init=} ;;
root=* ) root=${param#root=} ;;
rootdelay=* ) rootdelay=${param#rootdelay=} ;;
rootfstype=*) rootfstype=${param#rootfstype=} ;;
rootflags=* ) rootflags=${param#rootflags=} ;;
resume=* ) resume=${param#resume=} ;;
noresume ) noresume=true ;;
ro ) ro="ro" ;;
rw ) ro="rw" ;;
esac
done
# udevd location depends on version
if [ -x /sbin/udevd ]; then
UDEVD=/sbin/udevd
elif [ -x /lib/udev/udevd ]; then
UDEVD=/lib/udev/udevd
elif [ -x /lib/systemd/systemd-udevd ]; then
UDEVD=/lib/systemd/systemd-udevd
else
echo "Cannot find udevd nor systemd-udevd"
problem
fi
${UDEVD} --daemon --resolve-names=never
udevadm trigger
udevadm settle
if [ -f /etc/mdadm.conf ] ; then mdadm -As ; fi
if [ -x /sbin/vgchange ] ; then /sbin/vgchange -a y > /dev/null ; fi
if [ -n "$rootdelay" ] ; then sleep "$rootdelay" ; fi
do_try_resume # This function will not return if resuming from disk
do_mount_root
killall -w ${UDEVD##*/}
exec switch_root /.root "$init" "$@"
EOF
printf "Creating $INITRAMFS_FILE... "
binfiles="sh cat cp dd killall ls mkdir mknod mount "
binfiles="$binfiles umount sed sleep ln rm uname"
binfiles="$binfiles readlink basename"
# Systemd installs udevadm in /bin. Other udev implementations have it in /sbin
if [ -x /bin/udevadm ] ; then binfiles="$binfiles udevadm"; fi
sbinfiles="modprobe blkid switch_root"
#Optional files and locations
for f in mdadm mdmon udevd udevadm; do
if [ -x /sbin/$f ] ; then sbinfiles="$sbinfiles $f"; fi
done
# Add lvm if present (cannot be done with the others because it
# also needs dmsetup
if [ -x /sbin/lvm ] ; then sbinfiles="$sbinfiles lvm dmsetup"; fi
unsorted=$(mktemp /tmp/unsorted.XXXXXXXXXX)
DATADIR=/usr/share/mkinitramfs
INITIN=init.in
# Create a temporary working directory
WDIR=$(mktemp -d /tmp/initrd-work.XXXXXXXXXX)
# Create base directory structure
mkdir -p $WDIR/{bin,dev,lib/firmware,run,sbin,sys,proc,usr}
mkdir -p $WDIR/etc/{modprobe.d,udev/rules.d}
touch $WDIR/etc/modprobe.d/modprobe.conf
ln -s lib $WDIR/lib64
ln -s ../bin $WDIR/usr/bin
# Create necessary device nodes
mknod -m 640 $WDIR/dev/console c 5 1
mknod -m 664 $WDIR/dev/null c 1 3
# Install the udev configuration files
if [ -f /etc/udev/udev.conf ]; then
cp /etc/udev/udev.conf $WDIR/etc/udev/udev.conf
fi
for file in $(find /etc/udev/rules.d/ -type f) ; do
cp $file $WDIR/etc/udev/rules.d
done
# Install any firmware present
cp -a /lib/firmware $WDIR/lib
# Copy the RAID configuration file if present
if [ -f /etc/mdadm.conf ] ; then
cp /etc/mdadm.conf $WDIR/etc
fi
# Install the init file
install -m0755 $DATADIR/$INITIN $WDIR/init
if [ -n "$KERNEL_VERSION" ] ; then
if [ -x /bin/kmod ] ; then
binfiles="$binfiles kmod"
else
binfiles="$binfiles lsmod"
sbinfiles="$sbinfiles insmod"
fi
fi
# Install basic binaries
for f in $binfiles ; do
if [ -e /bin/$f ]; then d="/bin"; else d="/usr/bin"; fi
ldd $d/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy $d/$f bin
done
for f in $sbinfiles ; do
ldd /sbin/$f | sed "s/\t//" | cut -d " " -f1 >> $unsorted
copy $f sbin
done
# Add udevd libraries if not in /sbin
if [ -x /lib/udev/udevd ] ; then
ldd /lib/udev/udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted
elif [ -x /lib/systemd/systemd-udevd ] ; then
ldd /lib/systemd/systemd-udevd | sed "s/\t//" | cut -d " " -f1 >> $unsorted
fi
# Add module symlinks if appropriate
if [ -n "$KERNEL_VERSION" ] && [ -x /bin/kmod ] ; then
ln -s kmod $WDIR/bin/lsmod
ln -s kmod $WDIR/bin/insmod
fi
# Add lvm symlinks if appropriate
# Also copy the lvm.conf file
if [ -x /sbin/lvm ] ; then
ln -s lvm $WDIR/sbin/lvchange
ln -s lvm $WDIR/sbin/lvrename
ln -s lvm $WDIR/sbin/lvextend
ln -s lvm $WDIR/sbin/lvcreate
ln -s lvm $WDIR/sbin/lvdisplay
ln -s lvm $WDIR/sbin/lvscan
ln -s lvm $WDIR/sbin/pvchange
ln -s lvm $WDIR/sbin/pvck
ln -s lvm $WDIR/sbin/pvcreate
ln -s lvm $WDIR/sbin/pvdisplay
ln -s lvm $WDIR/sbin/pvscan
ln -s lvm $WDIR/sbin/vgchange
ln -s lvm $WDIR/sbin/vgcreate
ln -s lvm $WDIR/sbin/vgscan
ln -s lvm $WDIR/sbin/vgrename
ln -s lvm $WDIR/sbin/vgck
# Conf file(s)
cp -a /etc/lvm $WDIR/etc
fi
# Install libraries
sort $unsorted | uniq | while read library ; do
# linux-vdso and linux-gate are pseudo libraries and do not correspond to a file
# libsystemd-shared is in /lib/systemd, so it is not found by copy, and
# it is copied below anyway
if [[ "$library" == linux-vdso.so.1 ]] ||
[[ "$library" == linux-gate.so.1 ]] ||
[[ "$library" == libsystemd-shared* ]]; then
continue
fi
copy $library lib
done
if [ -d /lib/udev ]; then
cp -a /lib/udev $WDIR/lib
fi
if [ -d /lib/systemd ]; then
cp -a /lib/systemd $WDIR/lib
fi
if [ -d /lib/elogind ]; then
cp -a /lib/elogind $WDIR/lib
fi
# Install the kernel modules if requested
if [ -n "$KERNEL_VERSION" ]; then
find \
/lib/modules/$KERNEL_VERSION/kernel/{crypto,fs,lib} \
/lib/modules/$KERNEL_VERSION/kernel/drivers/{block,ata,md,firewire} \
/lib/modules/$KERNEL_VERSION/kernel/drivers/{scsi,message,pcmcia,virtio} \
/lib/modules/$KERNEL_VERSION/kernel/drivers/usb/{host,storage} \
-type f 2> /dev/null | cpio --make-directories -p --quiet $WDIR
cp /lib/modules/$KERNEL_VERSION/modules.{builtin,order} \
$WDIR/lib/modules/$KERNEL_VERSION
depmod -b $WDIR $KERNEL_VERSION
fi
( cd $WDIR ; find . | cpio -o -H newc --quiet | gzip -9 ) > $INITRAMFS_FILE
# Prepare early loading of microcode if available
if ls /lib/firmware/intel-ucode/* >/dev/null 2>&1 ||
ls /lib/firmware/amd-ucode/* >/dev/null 2>&1; then
# first empty WDIR to reuse it
rm -r $WDIR/*
DSTDIR=$WDIR/kernel/x86/microcode
mkdir -p $DSTDIR
if [ -d /lib/firmware/amd-ucode ]; then
cat /lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin
fi
if [ -d /lib/firmware/intel-ucode ]; then
cat /lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin
fi
( cd $WDIR; find . | cpio -o -H newc --quiet ) > microcode.img
cat microcode.img $INITRAMFS_FILE > tmpfile
mv tmpfile $INITRAMFS_FILE
rm microcode.img
fi
# Remove the temporary directories and files
rm -rf $WDIR $unsorted
printf "done.\n"
EOF
chmod 0755 /sbin/mkinitramfs