commit 608b912088ac9d9b9c81ad342d2aa8c712b9bc0b
parent abbf37adaaad1b972cb0843374c7ba1779e688af
Author: emmett1 <emmett1.2miligrams@gmail.com>
Date: Sun, 14 Jun 2020 00:57:11 +0800
updated
Diffstat:
13 files changed, 442 insertions(+), 220 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,7 +1,9 @@
BINDIR = /usr/bin
DATADIR = /usr/share/mkinitrd
+HOOKDIR = /etc/mkinitrd.d
IBINDIR = $(DESTDIR)$(BINDIR)
IDATADIR = $(DESTDIR)$(DATADIR)
+IHOOKDIR = $(DESTDIR)$(HOOKDIR)
all:
@echo "Run 'make install' to install"
@@ -11,9 +13,13 @@ install:
install -m755 mkinitrd $(IBINDIR)
install -d $(IDATADIR)
install -m755 init $(IDATADIR)
+ install -d $(IHOOKDIR)
+ install -m644 hook/* $(IHOOKDIR)
+ install -m644 mkinitrd.conf $(DESTDIR)/etc/mkinitrd.conf
uninstall:
rm -f $(IBINDIR)/mkinitrd
rm -f $(IDATADIR)/init
+ rm -f $(DESTDIR)/etc/mkinitrd.conf
.PHONY: all install uninstall
diff --git a/hook/automod.build b/hook/automod.build
@@ -0,0 +1,6 @@
+# build hook autodetect currently loaded modules to include into initrd
+
+for mod in /sys/module/*; do
+ mod=$(basename $mod)
+ modinfo -k $KERNEL $mod &>/dev/null && add_module $mod
+done
diff --git a/hook/base.build b/hook/base.build
@@ -0,0 +1,15 @@
+# build hook for basic binaries, directories, files and stuff
+
+# basic binaries
+for b in bash sh cat cp killall ls mkdir mount umount sed awk sleep ln rm setsid mountpoint tac \
+ uname readlink basename modprobe blkid switch_root depmod kmod lsmod insmod chroot chmod; do
+ add_binary $b
+done
+
+# add modprobe.d dir
+if [ -d /etc/modprobe.d/ ]; then
+ add_dir /etc/modprobe.d/
+fi
+
+# add required terminfo
+add_file /usr/share/terminfo/l/linux
diff --git a/hook/livecd.build b/hook/livecd.build
@@ -0,0 +1,11 @@
+# build hook for livecd
+
+add_binary /lib/udev/cdrom_id
+add_binary blockdev
+add_binary losetup
+
+add_file /lib/udev/rules.d/60-cdrom_id.rules
+
+add_module cdrom
+add_module loop
+add_module overlay
diff --git a/hook/livecd.run b/hook/livecd.run
@@ -0,0 +1,49 @@
+# run hook for livecd only execute when $root is empty
+
+# if root is set, mean not live boot
+[ "$root" ] && return
+
+mkdir $newroot
+
+modprobe loop
+modprobe cdrom
+modprobe overlay
+
+LIVECDLABEL=LIVECD
+MEDIA=/dev/disk/by-label/$LIVECDLABEL
+MEDIUM=/run/initramfs/medium
+SYSTEM=/run/initramfs/system
+WRITEDIR=/run/initramfs/overlayfs/write
+WORKDIR=/run/initramfs/overlayfs/work
+sfsimg=$MEDIUM/boot/filesystem.sfs
+livedelay=${livedelay:-5}
+
+if [ ! -e $MEDIA ]; then
+ msg "wait $delay seconds..."
+ sleep $delay
+ if [ ! -e $MEDIA ]; then
+ msg "media is not appeared even after wait $delay seconds..."
+ msg "try increase delay by append 'livedelay=<seconds>' to boot cmdline"
+ sleep 99999
+ fi
+fi
+
+mkdir -p $MEDIUM $SYSTEM $WRITEDIR $WORKDIR
+
+mount -o ro $MEDIA $MEDIUM || problem
+sfs_dev=$(losetup --find --show --read-only $sfsimg) || problem
+mount -o defaults -r $sfs_dev $SYSTEM || problem
+mount -t overlay overlay -o upperdir=$WRITEDIR,lowerdir=$SYSTEM,workdir=$WORKDIR $newroot || problem
+
+# tell system to skip fsck during startup
+> $newroot/fastboot
+
+if [ -d "$MEDIUM"/rootfs ]; then
+ cp -Ra "$MEDIUM"/rootfs/* $newroot
+fi
+
+# execute custom script before switch root
+if [ -f $newroot/root/custom_script.sh ]; then
+ chmod +x $newroot/root/custom_script.sh
+ chroot $newroot sh /root/custom_script.sh
+fi
diff --git a/hook/lvm.build b/hook/lvm.build
@@ -0,0 +1,8 @@
+# build hook for lvm
+
+for i in lvm dmsetup lvchange lvrename lvrename lvextend lvcreate lvdisplay lvscan \
+ pvchange pvck pvcreate pvdisplay pvscan \
+ vgchange vgcreate vgscan vgrename vgck; do
+ add_binary $i
+done
+add_dir /etc/lvm
diff --git a/hook/modules.build b/hook/modules.build
@@ -0,0 +1,12 @@
+# build hook to include kernel modules
+
+# kernel modules
+for mod in kernel/crypto kernel/fs kernel/lib kernel/drivers/block kernel/drivers/ata kernel/drivers/md \
+ kernel/drivers/firewire kernel/drivers/input kernel/drivers/scsi kernel/drivers/message \
+ kernel/drivers/pcmcia kernel/drivers/virtio kernel/drivers/hid kernel/drivers/usb/host kernel/drivers/usb/storage; do
+ FTGT="$FTGT /lib/modules/$KERNEL/$mod"
+done
+for m in $(find $FTGT -type f -name "*.ko*" 2> /dev/null); do
+ m=$(echo ${m%*.ko*})
+ add_module $(basename $m)
+done
diff --git a/hook/udev.build b/hook/udev.build
@@ -0,0 +1,18 @@
+# build hook to include udev stuffs
+
+add_file /etc/udev/udev.conf
+add_file /lib/udev/rules.d/50-udev-default.rules
+add_file /lib/udev/rules.d/60-persistent-storage.rules
+add_file /lib/udev/rules.d/64-btrfs.rules
+add_file /lib/udev/rules.d/80-drivers.rules
+add_binary udevadm
+add_binary udevd
+add_binary /lib/udev/ata_id
+add_binary /lib/udev/scsi_id
+
+# Add udevd if not in PATH
+if [ -x /lib/udev/udevd ] ; then
+ add_binary /lib/udev/udevd
+elif [ -x /lib/systemd/systemd-udevd ] ; then
+ add_binary /lib/systemd/systemd-udevd
+fi
diff --git a/hook/udev.cleanup b/hook/udev.cleanup
@@ -0,0 +1,3 @@
+# cleanup hook for udev
+udevadm control --exit
+udevadm info --cleanup-db
diff --git a/hook/udev.run b/hook/udev.run
@@ -0,0 +1,7 @@
+# run hook for udev
+
+udevd --daemon --resolve-names=never
+udevadm trigger --action=add --type=subsystems
+udevadm trigger --action=add --type=devices
+udevadm trigger --action=change --type=devices
+udevadm settle
diff --git a/init b/init
@@ -7,107 +7,54 @@ shell() {
}
problem() {
- printf "Encountered a problem!\n\nDropping you to a shell.\n\n"
+ msg "Encountered a problem, dropping you to a shell."
shell
}
msg() {
+ [ "$quiet" = y ] && return
echo ":: $*"
}
-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 $newroot
- [ -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
-
+mount_root() {
+ mkdir $newroot
+ if [ ! "$device" ]; then
+ msg "device not scpecified!"
+ problem
+ fi
while [ ! -b "$device" ] ; do
no_device $device
problem
- done
-
- if ! mount -n -t "$rootfstype" -o "$rootflags" "$device" $newroot ; then
- no_mount $device
- cat /proc/partitions
- while true ; do sleep 10000 ; done
+ done
+ if ! mount -n ${rootfstype:+-t $rootfstype} -o ${rwopt:-ro}${rootflags:+,$rootflags} "$device" "$newroot" ; then
+ msg "failed mount root device: $device"
+ shell
fi
}
-do_boot_live() {
- mkdir $newroot
- modprobe loop
-
- MEDIA=/dev/disk/by-label/LIVECD
- MEDIUM=/run/initramfs/medium
- SYSTEM=/run/initramfs/system
- WRITEDIR=/run/initramfs/overlayfs/write
- WORKDIR=/run/initramfs/overlayfs/work
- sfsimg=$MEDIUM/boot/filesystem.sfs
- delay=${delay:-5}
-
- mkdir -p $MEDIUM $SYSTEM $WRITEDIR $WORKDIR
-
- if [ ! -e $MEDIA ]; then
- msg "wait $delay seconds..."
- sleep $delay
- if [ ! -e $MEDIA ]; then
- msg "media is not appeared even after wait $delay seconds..."
- msg "try increase delay by append 'delay=<seconds>' to boot cmdline"
- sleep 9999
- fi
- fi
-
- mount -o ro $MEDIA $MEDIUM || problem
- sfs_dev=$(losetup --find --show --read-only $sfsimg)
- mount -o defaults -r $sfs_dev $SYSTEM || problem
- mount -t overlay overlay -o upperdir=$WRITEDIR,lowerdir=$SYSTEM,workdir=$WORKDIR $newroot || problem
-
- # Tell system to skip fsck during startup
- > $newroot/fastboot
-
- if [ -d "$MEDIUM"/rootfs ]; then
- cp -Ra "$MEDIUM"/rootfs/* $newroot
- fi
-
- # Execute custom script before switch root
- if [ -f $newroot/root/custom_script.sh ]; then
- chmod +x $newroot/root/custom_script.sh
- chroot $newroot sh /root/custom_script.sh
- fi
-}
+parse_cmdline() {
+ read -r cmdline < /proc/cmdline
+
+ for param in $cmdline ; do
+ case $param in
+ *=*) key=${param%%=*}; value=${param#*=} ;;
+ '#'*) break ;;
+ *) key=$param
+ esac
+ case $key in
+ ro|rw) rwopt=$key ;;
+ [![:alpha:]_]*|[[:alpha:]_]*[![:alnum:]_]*) ;;
+ *) eval "$key"=${value:-y} ;;
+ esac
+ unset key value
+ done
-do_try_resume() {
- case "$resume" in
- UUID=* ) eval $resume; resume="/dev/disk/by-uuid/$UUID" ;;
- LABEL=*) eval $resume; resume="/dev/disk/by-label/$LABEL" ;;
+ 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" ;;
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
@@ -118,67 +65,49 @@ rootfstype=auto
ro="ro"
rootflags=
device=
-resume=
-noresume=false
mount -t proc proc /proc -o nosuid,noexec,nodev
mount -t sysfs sys /sys -o nosuid,noexec,nodev
mount -t devtmpfs dev /dev -o mode=0755,nosuid
mount -t tmpfs run /run -o nosuid,nodev,mode=0755
-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" ;;
- shell ) shell=true ;;
- live ) live=true ;;
- 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
+parse_cmdline
-${UDEVD} --daemon --resolve-names=never
-udevadm trigger --action=add --type=subsystems
-udevadm trigger --action=add --type=devices
-udevadm trigger --action=change --type=devices
-udevadm settle
+if [ "$break" = y ] || [ "$break" = pre-mount ]; then
+ msg "break pre-mount requested."
+ shell
+fi
-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
+# run hook
+if [ -f /runhook.order ]; then
+ for hook in $(cat /runhook.order); do
+ if [ -f /etc/mkinitrd.d/$hook.run ]; then
+ msg "running run hook: $hook"
+ . /etc/mkinitrd.d/$hook.run
+ fi
+ done
+fi
-if [ "$shell" = true ]; then
- echo "shell requested, drop to shell"
- shell
+# mount root device is root is set
+if [ "$root" ]; then
+ msg "mounting root: $root"
+ mount_root
fi
-if [ "$live" = true ]; then
- do_boot_live
-else
- do_try_resume # This function will not return if resuming from disk
- do_mount_root
+# run cleanup hook
+if [ -f /cleanuphook.order ]; then
+ for hook in $(tac /cleanuphook.order); do
+ if [ -f /etc/mkinitrd.d/$hook.cleanup ]; then
+ msg "running cleanup hook: $hook"
+ . /etc/mkinitrd.d/$hook.cleanup
+ fi
+ done
fi
-killall -w ${UDEVD##*/}
+if [ ! -d "$newroot" ] || [ ! "$(mountpoint $newroot)" ]; then
+ msg "seems no root device mounted on newroot."
+ problem
+fi
mount --move /proc $newroot/proc
mount --move /sys $newroot/sys
diff --git a/mkinitrd b/mkinitrd
@@ -7,14 +7,14 @@ add_file() {
if [ -f $1 ]; then
file=$1
else
- echo "missing file: $1"
+ msgwarn "missing file: $1"
return
fi
if [ -L $file ]; then
add_file $(readlink -f $file)
fi
if [ "${file:0:1}" != "/" ]; then
- echo "absolute source path needed: $file"
+ msgerr "absolute source path needed: $file"
return
fi
if [ "$2" ]; then
@@ -23,17 +23,16 @@ add_file() {
dest=${file/\//}
fi
if [ "${dest:0:1}" = "/" ]; then
- echo "destination path must without leading '/': $dest"
+ msgerr "destination path must without leading '/': $dest"
return
fi
mode=${3:-$(stat -c %a "$file")}
if [ ! "$mode" ]; then
- echo "failed get file mode: $file"
+ msgerr "failed get file mode: $file"
return
fi
install -Dm$mode $file $INITRDDIR/$dest
}
-
add_binary() {
# add_binary binary
@@ -41,7 +40,7 @@ add_binary() {
[ "$1" ] || return
bin=$(type -p $1)
if [ ! "$bin" ]; then
- echo "missing bin: $1"
+ msgwarn "missing binary: $1"
return
fi
if [ -x $INITRDDIR/$bin ]; then
@@ -54,7 +53,7 @@ add_binary() {
esac
lib=$(PATH=/lib:/lib64:/usr/lib type -p $i)
if [ ! "$lib" ]; then
- echo "missing lib: $i"
+ msgwarn "missing library: $i"
continue
fi
if [ -e $INITRDDIR/$lib ]; then
@@ -74,14 +73,14 @@ add_module() {
modpath=$(modinfo -k $KERNEL -F filename $1 | cut -d ' ' -f1 | head -n1)
[ "$modpath" = "name:" ] && return 0
else
- echo "missing module: $1"
+ msgwarn "missing module: $1"
return
fi
[ -f $INITDIR/lib/modules/$KERNEL/kernel/$(basename $modpath) ] && return
add_file "$modpath" lib/modules/$KERNEL/kernel/$(basename $modpath)
modinfo -F firmware -k $KERNEL $modname | while read -r line; do
if [ ! -f /lib/firmware/$line ]; then
- echo "missing firmware for $modname: $line"
+ msgwarn "missing firmware for $modname: $line"
else
add_file /lib/firmware/$line
fi
@@ -108,7 +107,7 @@ add_dir() {
[ "$1" ] || return
source=$1
if [ ! -d $source ]; then
- echo "directory not exist: $source"
+ msgerr "directory not exist: $source"
return
fi
if [ $2 ]; then
@@ -125,39 +124,198 @@ make_dir() {
local path=$1 mode=${2:-755}
[ "$path" ] || return
if [ ${path:0:1} = / ]; then
- echo "path should not leading '/': $path"
+ msgerr "path should not leading '/': $path"
return
fi
install -dm$mode $INITRDDIR/$path
}
-if [ $1 ] ; then
- KERNEL=$1
-else
- KERNEL=$(uname -r)
-fi
-INITRD=/boot/initrd-$KERNEL.img
+usage() {
+ cat << EOF
+Usage:
+ $(basename $0) [option] [argument]
+
+Options:
+ -k <version> custom kernel version (default: $KERNEL)
+ -o <output> custom output name (default: $INITRAMFS)
+ -i <init> custom init file (default: $INITIN)
+ -m <modules> add extra modules (comma separated)
+ -b <binaries add extra binary (comma separated)
+ -f <file> add extra file (comma separated & absolute path)
+ -c <config> use custom config (default: $CONFIG)
+ -A <hook> add extra hook (comma separated, precedence over -a, -s & HOOKS)
+ -a <hook> add extra hook (comma separated, precedence over -s & after HOOKS)
+ -s <hook> skip hook defined in HOOKS (comma separated)
+ -q quiet mode
+ -h print this help msg
-if [ ! -d "/lib/modules/$1" ] ; then
- echo "No modules directory named $1"
+EOF
+}
+
+needarg() {
+ if [ ! "$1" ]; then
+ echo "ERROR: argument is needed for this option!"
+ exit 1
+ fi
+}
+
+parse_opt() {
+ while [ $1 ]; do
+ case $1 in
+ -k) needarg $2
+ KERNEL=$2
+ shift ;;
+ -o) needarg $2
+ OUTPUT=$2
+ shift ;;
+ -i) needarg $2
+ INITIN=$2
+ shift ;;
+ -c) needarg $2
+ CONFIG=$2
+ shift ;;
+ -A) needarg $2
+ IFS=, read -r -a ADDEARLYHOOKS <<< $2
+ shift ;;
+ -a) needarg $2
+ IFS=, read -r -a ADDHOOKS <<< $2
+ shift ;;
+ -s) needarg $2
+ IFS=, read -r -a SKIPHOOKS <<< $2
+ shift ;;
+ -m) needarg $2
+ IFS=, read -r -a ADDMODULES <<< $2
+ shift ;;
+ -b) needarg $2
+ IFS=, read -r -a ADDBINARIES <<< $2
+ shift ;;
+ -f) needarg $2
+ IFS=, read -r -a ADDFILES <<< $2
+ shift ;;
+ -q) QUIET=1 ;;
+ -h) usage; exit 0 ;;
+ *) msgerr "Invalid option '$1'"
+ exit 1 ;;
+ esac
+ shift
+ done
+}
+
+cleanup() {
+ rm -fr "$INITRDDIR"
+}
+
+interrupted() {
+ cleanup
exit 1
-fi
+}
+
+echo() {
+ [ "$QUIET" ] && return
+ command echo "$*"
+}
+
+msg() {
+ echo ":: $*"
+}
+
+msgwarn() {
+ echo "WARNING: $*"
+}
+
+msgerr() {
+ echo "ERROR: $*"
+}
+
+KERNEL=$(uname -r)
+DATADIR=/usr/share/mkinitrd
+INITIN=init
+HOOKDIR=/etc/mkinitrd.d
+CONFFILE=/etc/mkinitrd.conf
+INITRD=initrd-$KERNEL.img
CPIO=$(type -p cpio)
CPIO=$(type -p bsdcpio)
+parse_opt $@
+
+if [ "$UID" != "0" ]; then
+ msgerr "need root access!"
+ exit 1
+fi
+
+if [ ! -d "/lib/modules/$KERNEL" ] ; then
+ msgerr "No modules directory named $KERNEL"
+ exit 1
+fi
+
if [ ! "$CPIO" ]; then
- echo "Either 'cpio' nor 'bsdcpio' not found"
+ msgerr "Either 'cpio' nor 'bsdcpio' not found"
exit 1
fi
-DATADIR=/usr/share/mkinitrd
-INITIN=init
+if [ ! -f "$CONFFILE" ]; then
+ msgerr "Config file not found: $CONFFILE"
+ exit 1
+else
+ . "$CONFFILE"
+fi
+
+if [ "$OUTPUT" ]; then
+ if [ $(basename $OUTPUT) != "$OUTPUT" ] && [ ! -d $(dirname $OUTPUT) ]; then
+ msgerr "directory '$(dirname $OUTPUT)' for output '$(basename $OUTPUT)' not exist."
+ exit 1
+ elif [ -d "$OUTPUT" ]; then
+ msgerr "'$OUTPUT' is a directory."
+ exit 1
+ fi
+ INITRD="$OUTPUT"
+fi
+
+# filter out skip hooks (-s)
+if [ "${#SKIPHOOKS[@]}" -gt 0 ] && [ "${#HOOKS[@]}" -gt 0 ]; then
+ for s in ${!SKIPHOOKS[@]}; do
+ for h in ${!HOOKS[@]}; do
+ if [ "${SKIPHOOKS[s]}" = "${HOOKS[h]}" ]; then
+ unset 'HOOKS[h]'
+ break
+ fi
+ done
+ done
+fi
+
+# add extra hooks (-a)
+if [ "${#ADDHOOKS[@]}" -gt 0 ]; then
+ HOOKS+=(${ADDHOOKS[@]})
+fi
+
+# add extra early hooks (-A)
+if [ "${#ADDEARLYHOOKS[@]}" -gt 0 ]; then
+ ADDEARLYHOOKS+=(${HOOKS[@]})
+ HOOKS=(${ADDEARLYHOOKS[@]})
+fi
+
+# add extra modules (-m)
+if [ "${#ADDMODULES[@]}" -gt 0 ]; then
+ MODULES+=(${ADDMODULES[@]})
+fi
+
+# add extra files (-f)
+if [ "${#ADDFILES[@]}" -gt 0 ]; then
+ FILES+=(${ADDFILES[@]})
+fi
+
+# add extra binary (-b)
+if [ "${#ADDBINARIES[@]}" -gt 0 ]; then
+ BINARIES+=(${ADDBINARIES[@]})
+fi
+
+trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
# create a temporary working directory
INITRDDIR=$(mktemp -d /tmp/initrd-work.XXXXXXXXXX)
-echo "Creating $INITRD... "
+echo "Generating initrd... "
# make required dirs
for d in dev run sys proc; do
@@ -167,81 +325,52 @@ done
# add the init file
add_file $DATADIR/$INITIN init 755
-# add required binaries
-for b in bash sh cat cp killall ls mkdir mount umount sed awk sleep ln rm setsid \
- uname readlink basename modprobe blkid switch_root depmod kmod lsmod insmod chroot chmod; do
- add_binary $b
+# run hook
+for hook in ${HOOKS[@]}; do
+ # run build hook
+ if [ -f "$HOOKDIR/$hook.build" ]; then
+ msg "running build hook: $hook"
+ . $HOOKDIR/$hook.build
+ fi
+ # add run & cleanup hook and list the order
+ if [ -f "$HOOKDIR/$hook.run" ]; then
+ add_file $HOOKDIR/$hook.run
+ echo $hook >> $INITRDDIR/runhook.order
+ fi
+ if [ -f "$HOOKDIR/$hook.cleanup" ]; then
+ add_file $HOOKDIR/$hook.cleanup
+ echo $hook >> $INITRDDIR/cleanuphook.order
+ fi
done
-# add modprobe.d dir
-if [ -d /etc/modprobe.d/ ]; then
- add_dir /etc/modprobe.d/
+if [ "${#BINARIES[@]}" -gt 0 ]; then
+ msg "adding extra binaries..."
+ for b in ${BINARIES[@]}; do
+ add_binary "$b"
+ done
fi
-# add required terminfo
-add_file /usr/share/terminfo/l/linux
-
-# udev
-if [ -f /etc/udev/udev.conf ]; then
- add_file /etc/udev/udev.conf
- add_dir /lib/udev/rules.d
- add_dir /etc/udev/rules.d/
- add_binary udevadm
- add_binary udevd
- add_binary /lib/udev/ata_id
- add_binary /lib/udev/scsi_id
- # Add udevd if not in PATH
- if [ -x /lib/udev/udevd ] ; then
- add_binary /lib/udev/udevd
- elif [ -x /lib/systemd/systemd-udevd ] ; then
- add_binary /lib/systemd/systemd-udevd
- fi
+if [ "${#MODULES[@]}" -gt 0 ]; then
+ msg "adding extra modules..."
+ for m in ${MODULES[@]}; do
+ add_module "$m"
+ done
fi
-# LVM
-if [ $(type -p lvm) ]; then
- for i in lvm dmsetup lvchange lvrename lvrename lvextend lvcreate lvdisplay lvscan \
- pvchange pvck pvcreate pvdisplay pvscan \
- vgchange vgcreate vgscan vgrename vgck; do
- add_binary $i
+if [ "${#FILES[@]}" -gt 0 ]; then
+ msg "adding extra files..."
+ for f in ${FILES[@]}; do
+ add_file "$f"
done
- add_dir /etc/lvm
fi
-# systemd
-for dir in /lib/systemd /lib/elogind; do
- if [ -d $dir ]; then
- add_dir $dir
- fi
-done
-
-# for livecd
-add_binary /lib/udev/cdrom_id
-add_binary blockdev
-add_binary losetup
-add_module cdrom
-add_module loop
-add_module overlay
-
-# kernel modules
-for mod in kernel/crypto kernel/fs kernel/lib kernel/drivers/block kernel/drivers/ata kernel/drivers/md \
- kernel/drivers/firewire kernel/drivers/input kernel/drivers/scsi kernel/drivers/message \
- kernel/drivers/pcmcia kernel/drivers/virtio kernel/drivers/hid kernel/drivers/usb/host kernel/drivers/usb/storage; do
- FTGT="$FTGT /lib/modules/$KERNEL/$mod"
-done
-for m in $(find $FTGT -type f -name "*.ko*" 2> /dev/null); do
- m=$(echo ${m%*.ko*})
- add_module $(basename $m)
-done
-
finalize_modules
-( cd $INITRDDIR ; find . | $CPIO -o -H newc --quiet | gzip -9 ) > $INITRD
+( cd $INITRDDIR ; find . | LANG=C $CPIO -o -H newc --quiet | gzip -9 ) > $INITRD
# Remove the temporary directories
-rm -rf $INITRDDIR
+cleanup
-size=$(du -sh $INITRD | awk '{print $1}')
-echo "done ($size)"
+echo "Generating initrd done: $INITRD ($(du -sh $INITRD | awk '{print $1}'))"
exit 0
diff --git a/mkinitrd.conf b/mkinitrd.conf
@@ -0,0 +1,29 @@
+#
+# This file is sourced by mkinitrd
+#
+
+# add your extra binaries to initrd
+# for binary outside PATH, enter absolute path
+# shared libraries will automatically detected and added
+BINARIES=()
+
+# add your extra files from your system to initrd
+# use absolute path
+# if symlink, real file automatically detected and added
+FILES=()
+
+# add your extra kernel modules to initrd
+# module dependencies will automatically detected and added
+# firmware also automatically detected and added
+MODULES=()
+
+# build/run/cleanup hook
+# hook directory is /etc/mkinitrd.d
+# only build hook (*.build) will be executed when building initrd
+# run (*.run) and cleanup (*.cleanup) hook if exist will be added into initrd
+# order is matter for run and cleanup hook
+# cleanup hook will be executed reversely
+HOOKS=(base udev modules)
+
+# change custom name and path for initrd output
+#INITRD="initrd-$KERNEL.img"