mkinitrd

Cool project repo :D
git clone git://git.emmett1.my/mkinitrd.git
Log | Files | Refs

commit a389e1424648cf4f8f0f7d94b7144ebd474ac737
parent eb78c20706aea33a099f8e8fa4d84a3309aa6384
Author: emmett1 <emmett1.2miligrams@protonmail.com>
Date:   Thu, 26 Dec 2024 01:14:24 +0800

posixify

Diffstat:
Mhook/automod.build | 3+--
Mhook/livecd.build | 4++--
Mhook/lvm.build | 2+-
Mhook/modules.build | 4++--
Mhook/udev.build | 12++++++------
Mmkinitrd | 333++++++++++++++++++++++++-------------------------------------------------------
Mmkinitrd.conf | 8++++----
7 files changed, 118 insertions(+), 248 deletions(-)

diff --git a/hook/automod.build b/hook/automod.build @@ -1,6 +1,5 @@ # 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 + modinfo -k $KERNEL ${mod##*/} >/dev/null 2>&1 && add_module ${mod##*/} done diff --git a/hook/livecd.build b/hook/livecd.build @@ -1,10 +1,10 @@ # build hook for livecd -add_binary /lib/udev/cdrom_id +add_binary /usr/lib/udev/cdrom_id add_binary blockdev add_binary losetup -add_file /lib/udev/rules.d/60-cdrom_id.rules +add_file /usr/lib/udev/rules.d/60-cdrom_id.rules add_module cdrom add_module loop diff --git a/hook/lvm.build b/hook/lvm.build @@ -5,4 +5,4 @@ for i in lvm dmsetup lvchange lvrename lvrename lvextend lvcreate lvdisplay lvsc vgchange vgcreate vgscan vgrename vgck; do add_binary $i done -add_dir /etc/lvm +[ -d /etc/lvm ] && add_dir /etc/lvm diff --git a/hook/modules.build b/hook/modules.build @@ -7,6 +7,6 @@ for mod in kernel/crypto kernel/fs kernel/lib kernel/drivers/block kernel/driver 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) + m=${m%*.ko*} + add_module ${m##*/} done diff --git a/hook/udev.build b/hook/udev.build @@ -1,14 +1,14 @@ # 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_file /usr/lib/udev/rules.d/50-udev-default.rules +add_file /usr/lib/udev/rules.d/60-persistent-storage.rules +add_file /usr/lib/udev/rules.d/64-btrfs.rules +add_file /usr/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_binary /usr/lib/udev/ata_id +add_binary /usr/lib/udev/scsi_id # Add udevd if not in PATH if [ -x /lib/udev/udevd ] ; then diff --git a/mkinitrd b/mkinitrd @@ -1,133 +1,84 @@ -#!/bin/bash +#!/bin/sh add_file() { - # add_file file [ dest ][ mode ] - local file dest mode + # add_file file [ "$1" ] || return - if [ -f $1 ]; then - file=$1 - else - msgwarn "missing file: $1" - return - fi - if [ -L $file ]; then - add_file $(readlink -f $file) - fi - if [ "${file:0:1}" != "/" ]; then - msgerr "absolute source path needed: $file" - return - fi - if [ "$2" ]; then - dest="$2" - else - dest=${file/\//} - fi - if [ "${dest:0:1}" = "/" ]; then - msgerr "destination path must without leading '/': $dest" - return - fi - mode=${3:-$(stat -c %a "$file")} - if [ ! "$mode" ]; then - msgerr "failed get file mode: $file" - return - fi - install -Dm$mode $file $INITRDDIR/$dest + while [ "$1" ]; do + if [ -f $1 ]; then + file=$1 + else + msgwarn "missing file: $1" + return + fi + if [ -L $file ]; then + add_file $(readlink -f $file) + fi + [ "${file#/}" = "$file" ] && { msgwarn "absolute source path needed: $file"; return; } + mkdir -p $INITRDDIR/${file%/*} + install $file $INITRDDIR/${file%/*} + shift + done } add_binary() { # add_binary binary - local bin lib [ "$1" ] || return - bin=$(type -p $1) - if [ ! "$bin" ]; then - msgwarn "missing binary: $1" - return - fi - if [ -x $INITRDDIR/$bin ]; then - return - fi - add_file $bin - for i in $(ldd $bin | sed "s/\t//" | cut -d " " -f1); do - case $i in - linux-vdso.so.1|linux-gate.so.1) continue;; - esac - lib=$(PATH=/lib:/lib64:/usr/lib type -p $i) - if [ ! "$lib" ]; then - msgwarn "missing library: $i" - continue - fi - if [ -e $INITRDDIR/$lib ]; then - continue - fi - add_file $lib + while [ "$1" ]; do + bin=$(command -v $1) + [ "$bin" ] || { msgwarn "missing binary: $1"; return; } + [ -x $INITRDDIR/$bin ] && return + add_file $bin + for i in $(ldd $bin | sed "s/\t//" | cut -d " " -f1); do + case $i in + linux-vdso.so.1|linux-gate.so.1) continue;; + esac + lib=$(PATH=/lib:/lib64:/usr/lib:/usr/lib64 command -v $i) + [ "$lib" ] || { msgwarn "missing library: $i"; continue; } + [ -e $INITRDDIR/$lib ] && continue + add_file $lib + done + shift done } add_module() { # add_module modname - local modname modpath [ "$1" ] || return - if modinfo -k $KERNEL $1 &>/dev/null; then - modname=$(modinfo -k $KERNEL -F name $1 | cut -d ' ' -f1 | head -n1) - [ "$modname" = "name:" ] && return 0 - modpath=$(modinfo -k $KERNEL -F filename $1 | cut -d ' ' -f1 | head -n1) - [ "$modpath" = "name:" ] && return 0 - else - 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 - msgwarn "missing firmware for $modname: $line" + while [ "$1" ]; do + if [ "$(modinfo -k $KERNEL $1)" ]; then + modname=$(modinfo -k $KERNEL -F name $1 | cut -d ' ' -f1 | head -n1) + [ "$modname" = "name:" ] && return 0 + modpath=$(modinfo -k $KERNEL -F filename $1 | cut -d ' ' -f1 | head -n1) + [ "$modpath" = "(builtin)" ] && return 0 else - add_file /lib/firmware/$line + msgwarn "missing module: $1" + return fi - done - modinfo -F depends -k $KERNEL $modname | while IFS=',' read -r -a line; do - for l in ${line[@]}; do - add_module "$l" + [ -f $INITRDDIR/$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 + msgwarn "missing firmware for $modname: $line" + else + add_file /lib/firmware/$line + fi done + m=$(modinfo -F depends -k $KERNEL $modname | tr ',' ' ') + [ "$m" ] && add_module $m + shift done } -finalize_modules() { - local file - [ -d $INITRDDIR/lib/modules/$KERNEL/kernel ] || return - for file in /lib/modules/$KERNEL/modules.*; do - add_file $file - done - awk -F'/' '{ print "kernel/" $NF }' /lib/modules/$KERNEL/modules.order > $INITDIR/lib/modules/$KERNEL/modules.order - depmod -b $INITRDDIR $KERNEL -} - add_dir() { - # add_dir source [ target ] + # add_dir source [ "$1" ] || return - source=$1 - if [ ! -d $source ]; then - msgerr "directory not exist: $source" - return - fi - if [ $2 ]; then - target=$2 - else - target=$(dirname $source) - fi - mkdir -p $INITRDDIR/$target - cp -a $source $INITRDDIR/$target -} - -make_dir() { - # make_dir path [ mode ] - local path=$1 mode=${2:-755} - [ "$path" ] || return - if [ ${path:0:1} = / ]; then - msgerr "path should not leading '/': $path" - return - fi - install -dm$mode $INITRDDIR/$path + while [ "$1" ]; do + [ -d $1 ] || { msgerr "directory not exist: $1"; return; } + set -- ${1%/} # crunch last slash (/) + mkdir -p $INITRDDIR/${1%/*} + cp -ra $1 $INITRDDIR/${1%/*} + shift + done } usage() { @@ -160,44 +111,22 @@ needarg() { } parse_opt() { - while [ $1 ]; do + 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 ;; + -k) KERNEL=$2;; + -o) OUTPUT=$2;; + -i) INITIN=$2;; + -c) CONFIG=$2;; + -A) ADDEARLYHOOKS="$ADDEARLYHOOKS $2";; + -a) ADDHOOKS="$ADDHOOKS $2";; + -s) SKIPHOOKS="$SKIPHOOKS $2";; + -m) ADDMODULES="$ADDMODULES $2";; + -b) ADDBINARIES="$ADDBINARIES $2";; + -f) ADDFILES="$ADDFILES $2";; -h) usage; exit 0 ;; - *) msgerr "Invalid option '$1'" - exit 1 ;; + *) msgerr "Invalid option '$1'"; exit 1 ;; esac - shift + shift 2 done } @@ -225,6 +154,7 @@ msgwarn() { msgerr() { echo "ERROR: $*" + exit 1 } KERNEL=$(uname -r) @@ -234,83 +164,38 @@ HOOKDIR=/etc/mkinitrd.d CONFFILE=/etc/mkinitrd.conf INITRD=initrd-$KERNEL.img -CPIO=$(type -p cpio) -CPIO=$(type -p bsdcpio) +CPIO=$(command -v cpio) +CPIO=$(command -v bsdcpio) parse_opt $@ -if [ "$UID" != "0" ]; then - msgerr "need root access!" - exit 1 -fi +[ "$(id -u)" = "0" ] || msgerr "need root access!" +[ -d "/lib/modules/$KERNEL" ] || msgerr "No modules directory named $KERNEL" +[ "$CPIO" ] || msgerr "Either 'cpio' nor 'bsdcpio' not found." +[ -f "$CONFFILE" ] || msgerr "Config file not found: $CONFFILE" -if [ ! -d "/lib/modules/$KERNEL" ] ; then - msgerr "No modules directory named $KERNEL" - exit 1 -fi - -if [ ! "$CPIO" ]; then - msgerr "Either 'cpio' nor 'bsdcpio' not found" - exit 1 -fi - -if [ ! -f "$CONFFILE" ]; then - msgerr "Config file not found: $CONFFILE" - exit 1 -else - . "$CONFFILE" -fi +. "$CONFFILE" 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 + [ -d "$OUTPUT" ] && msgerr "'$OUTPUT' is a directory." + #[ -d ${OUTPUT%/*} ] || msgerr "directory '${OUTPUT%/*}' for output '$(basename $OUTPUT)' not exist." 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 +if [ "$SKIPHOOKS" ]; then + for s in $SKIPHOOKS; do + HOOKS=$(echo $HOOKS | tr ' ' '\n' | grep -vx $s) done -fi +fi -# add extra hooks (-a) -if [ "${#ADDHOOKS[@]}" -gt 0 ]; then - HOOKS+=(${ADDHOOKS[@]}) -fi +[ "$ADDHOOKS" ] && HOOKS="$HOOKS $ADDHOOKS" # add extra hooks (-a) +[ "$ADDEARLYHOOKS" ] && HOOKS="$ADDEARLYHOOKS $HOOKS" # add extra early hooks (-A) +[ "$ADDMODULES" ] && MODULES="$MODULES $ADDMODULES" # add extra modules (-m) +[ "$ADDFILES" ] && FILES="$FILES $ADDFILES" # add extra files (-f) +[ "$ADDBINARIES" ] && BINARIES="$BINARIES $ADDBINARIES" # add extra binary (-b) -# 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 +trap "interrupted" 1 2 3 15 # create a temporary working directory INITRDDIR=$(mktemp -d /tmp/initrd-work.XXXXXXXXXX) @@ -319,14 +204,16 @@ echo "Generating initrd... " # make required dirs for d in dev run sys proc; do - make_dir $d + mkdir -p $INITRDDIR/$d done +ln -s . $INITRDDIR/usr # add the init file -add_file $DATADIR/$INITIN init 755 +cp $DATADIR/$INITIN $INITRDDIR/init +chmod +x $INITRDDIR/init # run hook -for hook in ${HOOKS[@]}; do +for hook in $HOOKS; do # run build hook if [ -f "$HOOKDIR/$hook.build" ]; then msg "running build hook: $hook" @@ -343,28 +230,12 @@ for hook in ${HOOKS[@]}; do fi done -if [ "${#BINARIES[@]}" -gt 0 ]; then - msg "adding extra binaries..." - for b in ${BINARIES[@]}; do - add_binary "$b" - done -fi - -if [ "${#MODULES[@]}" -gt 0 ]; then - msg "adding extra modules..." - for m in ${MODULES[@]}; do - add_module "$m" - done -fi - -if [ "${#FILES[@]}" -gt 0 ]; then - msg "adding extra files..." - for f in ${FILES[@]}; do - add_file "$f" - done -fi +[ "$BINARIES" ] && add_binary $BINARIES +[ "$MODULES" ] && add_module $MODULES +[ "$FILES" ] && add_file $FILES -finalize_modules +add_file /lib/modules/$KERNEL/modules.* +depmod -b $INITRDDIR $KERNEL ( cd $INITRDDIR ; find . | LANG=C $CPIO -o -H newc --quiet | gzip -9 ) > $INITRD diff --git a/mkinitrd.conf b/mkinitrd.conf @@ -5,17 +5,17 @@ # add your extra binaries to initrd # for binary outside PATH, enter absolute path # shared libraries will automatically detected and added -BINARIES=() +BINARIES="" # add your extra files from your system to initrd # use absolute path # if symlink, real file automatically detected and added -FILES=() +FILES="" # add your extra kernel modules to initrd # module dependencies will automatically detected and added # firmware also automatically detected and added -MODULES=() +MODULES="" # build/run/cleanup hook # hook directory is /etc/mkinitrd.d @@ -23,7 +23,7 @@ MODULES=() # 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) +HOOKS="base udev modules" # change custom name and path for initrd output #INITRD="initrd-$KERNEL.img"