#!/bin/sh # geninitrd # # by PLD Linux Team # # based on mkinitrd from RedHat Linux # # TODO: # - make udev start before insmods # - make proper use of USE_UDEV - don't copy rules if USE_UDEV is off no! # RCSID='$Id$' R=${RCSID#* * }; VERSION=${R%% *} PROGRAM=${0##*/} . /etc/rc.d/init.d/functions . /etc/geninitrd/functions . /etc/sysconfig/system COMPRESS=yes USERAIDSTART=yes USEMDADMSTATIC=no USEINSMODSTATIC=no USE_SUSPEND=yes USE_TUXONICE=no # it should be safe to remove scsi_mod from here, but I'm not sure... PRESCSIMODS="-scsi_mod unknown -sd_mod" PREIDEMODS="-ide-core unknown -ide-detect -ide-disk" PREIDEMODSOLD="-ide-probe -ide-probe-mod -ide-disk" target="" kernel="" force="" verbose="" MODULES="" img_vers="" fstab=/etc/fstab insmod=insmod modext=.o rootdev_nr=0 # device node for rootfs from fstab rootdev="" # requires bootsplash package to operate BOOT_SPLASH=no # requires splashutils package to operate FB_SPLASH=no # requires splashutils package to operate FB_CON_DECOR=no # internal variables # is /dev on tmpfs dev_mounted=no # is /proc mounted proc_mounted=no # is /sys mounted sys_mounted=no # is /tmp mounted on tmpfs tmp_mounted=no # are /dev nodes already created from /proc/devices info? proc_partitions=no # LVM devices that should not be included in vgscan on initrd lvm_ignore_devices='' # whether v86d should be installed need_v86d=0 # LVM volumes that are needed to activate # VG for root dev ROOTVG="" # VG for suspend resume dev SUSPENDVG="" # resume device resume_dev="" # if we should init NFS at boot have_nfs=no # if we should init LVM at boot have_lvm=no # if we should init md (softraid) at boot have_md=no # if we should init dmraid at boot have_dmraid=no # if we should init dm-multipath at boot have_multipath=no # dm-multipath wwid which is used for rootfs MPATH_WWID= usage() { uname_r=$(uname -r) echo "usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload ]" echo " [--with=] [--image-version] [--fstab=] [--nocompress]" echo " [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=]" echo " [--with-raidstart] [--without-raidstart] [--with-insmod-static]" echo " [--with-bootsplash] [--without-bootsplash]" echo " [--with-fbsplash] [--without-fbsplash]" echo " [--with-fbcondecor] [--without-fbcondecor]" echo " [--lvmtoolsversion=1|2] [--with-udev] [--without-udev]" echo " [--with-suspend] [--without-suspend]" echo " [--with-tuxonice] [--without-tuxonice]" echo " [--without-dmraid] [--without-multipath]" echo " [--without-blkid]" echo " " echo "" echo "example:" echo " $PROGRAM -f --initrdfs=rom /boot/initrd-$uname_r.gz $uname_r" exit 1 } msg() { echo "$PROGRAM: $*" } warn() { msg "WARNING: $*" >&2 } debug() { [ -n "$verbose" ] && msg "$*" >&2 } # aborts program abnormally die() { local rc=${2:-1} warn "ERROR: $1" exit $rc } # append text to /linuxrc # takes STDIN as input add_linuxrc() { cat >> "$RCFILE" } # generate code to mount /dev on tmpfs and create initial nodes # can be called multiple times. /dev is cleaned up (umounted) automatically at # the end of script. mount_dev() { if [ "$INITRDFS" = "initramfs" ]; then # initramfs is read-write filesystem, no need for tmpfs return fi # we already generated tmpfs code; return if is_yes "$dev_mounted"; then return fi dev_mounted=yes busybox_applet mount mknod mkdir add_linuxrc <<-EOF : 'Creating /dev' mount -o mode=0755 -t tmpfs none /dev mknod /dev/console c 5 1 mknod /dev/null c 1 3 mknod /dev/zero c 1 5 mkdir /dev/pts mkdir /dev/shm EOF } # generate code to mount /proc on initrd # can be called multiple times mount_proc() { if is_yes "$proc_mounted"; then return fi proc_mounted=yes if [ "$INITRDFS" = "initramfs" ]; then # /proc is mounted with initramfs 2.6.22.14 kernel # XXX: remove when it is clear why proc was already mounted echo "[ -f /proc/cmdline ] || mount -t proc none /proc" | add_linuxrc else echo "mount -t proc none /proc" | add_linuxrc fi } # generate code to mount /sys on initrd # can be called multiple times mount_sys() { if is_yes "$sys_mounted"; then return fi sys_mounted=yes echo "mount -t sysfs none /sys" | add_linuxrc } # generate code to mount /tmp on initrd # can be called multiple times mount_tmp() { if [ "$INITRDFS" = "initramfs" ]; then # initramfs is read-write filesystem, no need for tmpfs return fi if is_yes "$tmp_mounted"; then return fi tmp_mounted=yes echo "mount -t tmpfs none /tmp" | add_linuxrc } # unmount all mountpoints mounted by geninitrd umount_all() { add_linuxrc <<-'EOF' : Last shell before umounting all and giving control over to real init. debugshell EOF if is_yes "$dev_mounted"; then echo 'umount /dev' | add_linuxrc dev_mounted=no fi if is_yes "$proc_mounted"; then echo 'umount /proc' | add_linuxrc proc_mounted=no fi if is_yes "$sys_mounted"; then echo 'umount /sys' | add_linuxrc sys_mounted=no fi if is_yes "$tmp_mounted"; then echo 'umount /tmp' | add_linuxrc tmp_mounted=no fi } # Checks if busybox has support for APPLET(s) # Exits from geninitrd if the support is not present. # # NB! XXX do not output to STDOUT, it will appear in initrd images in some cases! busybox_applet() { local err=0 if [ -z "$busybox_functions" ]; then local tmp=$(/bin/initrd-busybox 2>&1) # BusyBox v1.1.3 says applet not found if it's not called 'busybox'. if [[ "$tmp" = *applet\ not\ found* ]]; then local t=$(mktemp -d) ln -s /bin/initrd-busybox $t/busybox local tmp=$($t/busybox 2>&1) rm -rf $t fi busybox_functions=$(echo "$tmp" | \ sed -ne '/Currently defined functions:/,$p' | \ xargs | sed -e 's,.*Currently defined functions: ,,' ) fi for applet in $*; do local have # try cache eval have='$'busybox_have_$applet if [ -z "$have" ]; then have=$(echo "$busybox_functions" | egrep -c "( |^)$applet(,|$)") if [ "$have" = 0 ]; then warn "This setup requires busybox-initrd compiled with applet '$applet' support" err=1 fi eval busybox_have_$applet=$have fi done if [ $err = 1 ]; then die "Aborted" fi } # Finds module dependencies # # @param $module # @param $mode [silent] # # Outputs each dependant module full path including the module itself. find_depmod() { local module="$1" local mode="$2" # backwards compatible, process $mode local modfile if [ "$mode" = "silent" ]; then modfile=$(modinfo -k $kernel -n $module 2>/dev/null) else modfile=$(modinfo -k $kernel -n $module) fi if [ ! -f "$modfile" ]; then if [ "$mode" != "silent" ]; then warn "$module: module not found for $kernel kernel" fi if ! is_no "$EXIT_IF_MISSING"; then exit 1 else warn "If $module isn't compiled in kernel then this initrd may not start your system." fi fi # This works when user has module-init-tools installed even on 2.4 kernels modprobe --set-version $kernel --show-depends $module | \ while read insmod modpath options; do echo $modpath done } find_firmware() { local module="$1" echo -n $(modinfo -k $kernel -F firmware $module 2>/dev/null | xargs) } findmodule() { local skiperrors="" local modName=$1 if [ ${modName#-} != $modName ]; then skiperrors=1 modName=${modName#-} fi # what's that? if [ "$modName" = "pluto" ]; then findmodule fc4 findmodule soc fi if [ "$modName" = "fcal" ]; then findmodule fc4 findmodule socal fi local mod depmod if [ "$skiperrors" = 1 ]; then depmod=$(find_depmod $modName silent) else depmod=$(find_depmod $modName) if [ $? != 0 ]; then exit 1 fi fi for mod in $depmod; do mod=${mod#/lib/modules/$kernel/} # add each module only once local m have=0 for m in $MODULES; do [ $m = $mod ] && have=1 done if [ $have = 0 ]; then MODULES="$MODULES $mod" # if we are adding uvesafb, we need v86d as well if [ "$modName" = "uvesafb" ]; then need_v86d=yes fi fi done } # install a file to temporary mount image. # it will operate recursively (copying directories) # and will symlink destinations if source is symlink. inst() { if [ $# -lt 2 ]; then die 'Usage: inst [] ' fi local src i=0 c=$(($# - 1)) while [ $i -lt $c ]; do src="$src $1" i=$((i + 1)) shift done local dest=$1 set -- $src debug "+ cp $* $DESTDIR$dest" cp -HR "$@" "$DESTDIR$dest" } inst_d() { if [ $# = 0 ]; then die 'Usage: inst_d ' fi for dir in "$@"; do install -d "$DESTDIR$dir" done } # install executable and it's shared libraries inst_exec() { if [ $# -lt 2 ]; then die 'Usage: inst_exec [, ] ' fi local src i=0 c=$(($# - 1)) while [ $i -lt $c ]; do src="$src $1" i=$((i + 1)) shift done local dest=$1 set -- $src inst "$@" $dest local lib libs=$(ldd "$@" | awk '/statically|linux-gate\.so/{next} NF == 2 {print $1} /=/{print $3}' | sort -u) for lib in $libs; do if [ ! -f "$DESTDIR/$_lib/${lib##*/}" ]; then inst_d /$_lib inst_exec $lib /$_lib fi done } # output modules.conf / modprobe.conf modprobe_conf() { echo "$modprobe_conf_cache" } # # defaults to modprobe -c if not told otherwise, this means include statements # work from there. cache_modprobe_conf() { if [ "$pack_version" -lt "002005" ]; then modulefile=/etc/modules.conf if [ ! -f "$modulefile" -a -f /etc/conf.modules ]; then modulefile=/etc/conf.modules fi fi if [ -n "$modulefile" ]; then debug "Using $modulefile for modules config" modprobe_conf_cache=$(cat $modulefile) else debug "Using modprobe -c to get modules config" modprobe_conf_cache=$(modprobe -c) fi } find_modules_md() { local found raidlevel if [ -f /etc/mdadm.conf ]; then debug "Finding RAID details using mdadm for rootdev=$1" eval `/sbin/mdadm -v --examine --scan --config=/etc/mdadm.conf | awk -v rootdev="$1" ' BEGIN { found = "no"; dev_list = ""; raidlevel = "" rootdev_devfs = rootdev; if (rootdev ~ /\/dev\/md\/[0-9]/) { gsub(/\/dev\/md\//,"/dev/md",rootdev_devfs); } } /^ARRAY/ { if (($2 == rootdev) || ($2 == rootdev_devfs)) { raidlevel=$3; gsub(/level=/,NUL,raidlevel); if (raidlevel ~ /^raid([0-6]|10)/) { gsub(/raid/,NUL,raidlevel); }; found="yes"; getline x; if (x ~ /devices=/) { dev_list = x; gsub(".*devices=", NUL, dev_list); gsub(",", " ", dev_list); } } } END { print "have_md=" found; print "raidlevel=" raidlevel; print "dev_list=\"" dev_list "\""; }'` fi if [ "$have_md" != "yes" -a -f /etc/raidtab ]; then die "raidtools are not longer supported. Please migrate to mdadm setup!" fi if is_yes "$have_md"; then case "$raidlevel" in [01]|10) findmodule "raid$raidlevel" ;; [456]) findmodule "-raid$raidlevel" findmodule "-raid456" ;; linear) findmodule "linear" ;; *) warn "raid level $number (in mdadm config) not recognized" ;; esac else die "RAID devices not found for \"$1\", check your configuration!" fi rootdev_nr=$(( $rootdev_nr + 1 )) eval "rootdev${rootdev_nr}=\"$1\"" eval "dev_list${rootdev_nr}=\"${dev_list}\"" for device in $dev_list; do find_modules_for_devpath $device done } find_modules_scsi() { local n for n in $PRESCSIMODS; do if [ "X$n" = "Xunknown" ]; then debug "Finding SCSI modules using scsi_hostadapter" local mod scsimodules=$(modprobe_conf | awk '/scsi_hostadapter/ && ! /^[\t ]*#/ { print $3; }') for mod in $scsimodules; do # for now allow scsi modules to come from anywhere. There are some # RAID controllers with drivers in block findmodule "$mod" done else findmodule "$n" fi done findmodule "-scsi_wait_scan" } find_modules_ide() { local devpath=$1 # remove partition, if any local disk=${devpath%[0-9]*} # set blockdev for rootfs (hda, sdc, ...) local rootblkdev=${disk#/dev/} local n if [ "$pack_version_long" -lt "002004021" ]; then debug "Finding IDE modules for kernels <= 2.4.20" for n in $PREIDEMODSOLD; do findmodule "$n" done else local tryauto=1 for n in $PREIDEMODS; do if [ "X$n" = "Xunknown" ]; then debug "Finding IDE modules using ide_hostadapter" local mod idemodules=$(modprobe_conf | awk '/ide_hostadapter/ && ! /^[\t ]*#/ { print $3; }') for mod in $idemodules; do tryauto=0; findmodule "$mod" done if [ "$tryauto" -eq 1 ]; then # If tryauto {{{ if [ -r /usr/share/pci-database/ide.pci -a -r /proc/bus/pci/devices ]; then debug "Finding IDE modules using PCI ID database" # Finding IDE modules using PCI ID database {{{ if is_yes "${ide_only_root}"; then if [ -f /sys/block/${rootblkdev}/device/../../vendor -a -f /sys/block/${rootblkdev}/device/../../device ]; then vendorid="$(awk ' { gsub(/0x/,NUL); print $0 } ' /sys/block/${rootblkdev}/device/../../vendor)" deviceid="$(awk ' { gsub(/0x/,NUL); print $0 } ' /sys/block/${rootblkdev}/device/../../device)" searchpciid="${vendorid}${deviceid}" elif [ -f /proc/ide/${rootblkdev}/../config ]; then searchpciid="$(awk ' /pci bus/ { print $7$9 } ' /proc/ide/${rootblkdev}/../config)" fi fi if [ -z "${searchpciid}" ]; then searchpciid="$(awk ' { print $2 } ' /proc/bus/pci/devices)" fi idemodules="" for nb in $searchpciid; do eval `awk -v pciid="$nb" '{ gsub("\t"," "); gsub(" +", " "); gsub("^ ",""); if (/^[\t ]*#/) next; compmod = $1 ""; # make sure comparison type will be string # cause pci IDs are hexadecimal numeric if (compmod == pciid) { module=$2; # min_kernel=$3; # now in ide.pci $3,$4 = vendor and device name # max_kernel=$4; # exit 0; } } END { print "module=" module "\nmin_kernel=" min_kernel "\nmax_kernel=\"" max_kernel "\"\n"; }' /usr/share/pci-database/ide.pci` [ -n "$module" ] && idemodules="$idemodules $module" done if is_yes "$(awk ' /ide=reverse/ { print "yes" } ' /proc/cmdline)"; then new_idemodules="" for nc in idemodules; do new_idemodules="$nc $new_idemodules" done idemodules="${new_idemodules}" fi if [ -z "$idemodules" ]; then echo "WARNING: rootfs on IDE device but no related modules found, loading ide-generic." idemodules="ide-generic" fi # }}} for nd in $idemodules; do findmodule "-$nd" done # }}} # else tryauto {{{ else [ -r /usr/share/pci-database/ide.pci ] || echo "WARNING: /usr/share/pci-database/ide.pci missing." [ -r /proc/bus/pci/devices ] || echo "WARNING: /proc/bus/pci/devices missing." echo "Automatic IDE modules finding not available." fi # }}} fi else findmodule "$n" fi done fi } # return true if node is lvm node is_lvm_node() { local node="$1" if [ ! -e "$node" ]; then warn "WARNING: check_lvm(): node $node doesn't exist!" return 1 fi # block-major-58 is lvm1 ls -lL "$node" 2> /dev/null | awk '{if (/^b/) { if ($5 == "58,") { exit 0; } else { exit 1; } } else { exit 1; }}' rc=$? if [ $rc = 0 ]; then debug "LVM check: $node is LVM v1 node" # is lvm1 return 0 fi if [ ! -x /sbin/lvm ]; then debug "LVM check: no lvm2 tools present to check" return 0 fi /sbin/lvm lvdisplay "$node" > /dev/null 2>&1 rc=$? if [ $rc -gt 127 ]; then # lvdisplay terminated by signal! most likely it segfaulted. die "Unexpected exit from 'lvdisplay $node': $rc - are your lvm tools broken?" fi if [ $rc = 0 ]; then debug "LVM check: $node is LVM v2 node" else debug "LVM check: $node is not any LVM node" fi return $rc } # return dependencies MAJOR:MINOR [MAJOR:MINOR] for DM_NAME # TODO: patch `dmsetup export` dm_deps() { local dm_name="$1" dmsetup deps $dm_name | sed -e 's/, /:/g;s/^.\+ dependencies[^:]: //;s/[()]//g;' } # export info from dmsetup # param can be: # - MAJOR:MINOR # - /dev/dm-MINOR # - /dev/mapper/DM_NAME dm_export() { local arg="$1" case "$arg" in *:*) local maj=${arg%:*} min=${arg#*:} dmsetup -j $maj -m $min export ;; /dev/dm-*) local min=${arg#*dm-} local maj=$(awk '$2 == "device-mapper" {print $1}' /proc/devices) dm_export $maj:$min ;; /dev/mapper/*) local dm_name=${arg#/dev/mapper/} dmsetup export $dm_name ;; *) die "dm_export: unexpected $arg" ;; esac } # find dm-multipath modules for $devpath # returns false if $devpath is not dm-multipath find_modules_multipath() { local devpath="$1" DM_NAME= eval $(dm_export "$devpath") if [ -z "$DM_NAME" ]; then die "dm_export failed unexpectedly" fi # Partition: # DM_NAME=LUN-28p1 # DM_UUID=part1-mpath-36006016002c11800a0aa05fbfae0db11 # Disk: # DM_NAME=LUN-28 # DM_UUID=mpath-36006016002c11800a0aa05fbfae0db11 MPATH_WWID=${DM_UUID##*-} local info=$(multipath -l $MPATH_WWID) if [ -z "$info" ]; then return 1 fi debug "Finding modules for dm-multipath (WWID=$MPATH_WWID)" have_multipath=yes local dev phydevs=$(echo "$info" | awk '$2 ~ /^[0-9]+:[0-9]+:[0-9]+:[0-9]+$/{printf("/dev/%s\n", $3)}') for dev in $phydevs; do find_modules_for_devpath $dev lvm_ignore_devices="$lvm_ignore_devices $dev" done local hw hwhandlers=$(echo "$info" | awk '/hwhandler=1/{sub(/.*hwhandler=1 /, ""); sub(/\]$/, ""); print}') for hw in $hwhandlers; do findmodule "dm-$hw" done local target targets=$(echo "$info" | awk '/prio=/{print $2}' | sort -u) for target in $targets; do findmodule "dm-$target" done findmodule "dm-mod" return 0 } # find dmraid modules for $devpath # returns false if $devpath is not on dmraid find_modules_dmraid() { local devpath="$1" # get blockdev itself (without partition) # /dev/mapper/sil_ahbgadcbchfc3 -> /dev/mapper/sil_ahbgadcbchfc local blockdev=${devpath%%[0-9]*} local raidname=${blockdev#/dev/mapper/} local found=0 local dev phydevs=$(dmraid -r -cdevpath,raidname | awk -F, -vv="$raidname" '{if ($2 == v) print $1}') for dev in $phydevs; do find_modules_for_devpath $dev lvm_ignore_devices="$lvm_ignore_devices $dev" found=1 done if [ $found = 0 ]; then return 1 fi findmodule "dm-mirror" have_dmraid=yes return 0 } # find modules for $devpath find_modules_for_devpath() { local devpath="$1" if [ -z "$devpath" ]; then die "No argument passed to find_modules_for_devpath() - is your /etc/fstab correct?" fi # /dev/dm-3 -> /dev/mapper/sil_ahbgadcbchfc3 case "$devpath" in /dev/dm-*) devpath=$(dm_longname "$devpath") ;; esac debug "Finding modules for device path $devpath" if is_yes "`echo "$devpath" | awk '/^([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:|\/dev\/nfs)/ { print "yes"; }'`"; then if [ ! -x /usr/bin/pcidev -a -z "$NFS_ETH_MODULES" ]; then die "root on NFS but /usr/bin/pcidev not found. Please install correct pci-database package and rerun $PROGRAM." fi if [ ! -f /proc/bus/pci/devices ]; then warn "Remember to add network card modules in /etc/sysconfig/geninitrd, example:" warn "BASICMODULES=\"e1000 ne2k-pci mii 8139too 3c59x\"" else local m [ -z "$NFS_ETH_MODULES" ] && NFS_ETH_MODULES=$(/usr/bin/pcidev /m net | xargs) warn "NOTE: Network card(s) module(s) $NFS_ETH_MODULES is for this machine" for m in $NFS_ETH_MODULES; do findmodule "$m" done fi findmodule "-ipv4" findmodule "nfs" have_nfs=yes warn "Remember to use \`root=/dev/ram0 init=/linuxrc' when starting kernel" warn "or you will have problems like init(xx) being child process of swapper(1)." return fi if [[ "$devpath" == /dev/md* ]]; then find_modules_md "$devpath" return fi if is_yes "$USE_MULTIPATH" && [[ "$devpath" == /dev/mapper/* ]]; then if find_modules_multipath "$devpath"; then return fi # fallback fi if is_yes "$USE_DMRAID" && is_yes "$(echo "$devpath" | awk '/^\/dev\/mapper\/(sil|hpt37x|hpt45x|isw|lsi|nvidia|pdc|sil|via|dos)_/ { print "yes"; }')"; then if find_modules_dmraid "$devpath"; then return fi # fallback fi if is_yes "$(echo "$devpath" | awk '/^\/dev\/(sd|scsi)/ { print "yes"; }')"; then find_modules_scsi return fi if is_yes "$(echo "$devpath" | awk '/^\/dev\/(hd|ide)/ { print "yes"; }')"; then find_modules_ide "$devpath" return fi if [[ "$devpath" == /dev/rd/* ]]; then findmodule "DAC960" return fi if [[ "$devpath" == /dev/ida/* ]]; then findmodule "cpqarray" return fi if [[ "$devpath" == /dev/cciss/* ]]; then findmodule "cciss" return fi if [[ "$devpath" == /dev/ataraid/* ]]; then find_modules_ide findmodule "ataraid" ataraidmodules=$(modprobe_conf | awk '/ataraid_hostadapter/ && ! /^[\t ]*#/ { print $3; }') if [ -n "$ataraidmodules" ]; then # FIXME: think about modules compiled in kernel die "ataraid_hostadapter alias not defined in modprobe.conf! Please set it and run $PROGRAM again." fi for n in $ataraidmodules; do findmodule "$n" done return fi # check to see if we need to set up a loopback filesystem if [[ "$devpath" == /dev/loop* ]]; then die "Sorry, root on loop device isn't supported." # TODO: rewrite for bsp and make nfs ready if [ ! -x /sbin/losetup ]; then die "losetup is missing" fi key="^# $(echo $devpath | awk -F/ '{print($3);}' | tr '[a-z]' '[A-Z]'):" if ! is_yes "`awk '/'$key'/ { print( "yes"); }' $fstab`"; then die "The root filesystem is on a $devpath, but there is no magic entry in $fstab for this device. Consult the $PROGRAM man page for more information" fi line="`awk '/'$key'/ { print $0; }' $fstab`" loopDev="$(echo $line | awk '{print $3}')" loopFs="$(echo $line | awk '{print $4}')" loopFile="$(echo $line | awk '{print $5}')" BASICMODULES="$BASICMODULES -loop" findmodule "-$loopFs" BASICMODULES="$BASICMODULES -${loopFs}" return fi if is_lvm_node "$devpath"; then node="$devpath" if [ ! -f /sbin/initrd-lvm -o ! -x /sbin/lvdisplay -o ! -x /sbin/pvdisplay ]; then die "root on LVM but /sbin/initrd-lvm, /sbin/lvdisplay and /sbin/pvdisplay not found. Please install lvm(2) and lvm(2)-initrd package and rerun $PROGRAM." fi if [ -z "$LVMTOOLSVERSION" ]; then LVMTOOLSVERSION=$(/sbin/initrd-lvm vgchange --version 2>/dev/null|head -n 1|awk '{gsub("vgchange: Logical Volume Manager ",NIL); gsub("LVM version: ",NIL); gsub(/\..*/,NIL); print $1}') if [ -z "$LVMTOOLSVERSION" ]; then die "Can't determine LVM tools version. Please set LVMTOOLSVERSION and rerun $PROGRAM." fi fi local vg=$(/sbin/lvdisplay -c "$node" 2> /dev/null | awk -F":" ' { print $2 } ') VGVOLUMES=$(echo $VGVOLUMES $vg | tr ' ' '\n' | sort -u) local pv=$(/sbin/pvdisplay -c 2>/dev/null | awk -F":" -v vg="$vg" ' BEGIN { devices="" } { if ($2 == vg) { devices = devices " " $1 } } END { print devices } ') PVDEVICES=$(echo $PVDEVICES $pv | tr ' ' '\n' | sort -u) if [ -n "$PVDEVICES" ]; then for device in $PVDEVICES; do find_modules_for_devpath $device done else die "I wasn't able to find PV (via lvdisplay and pvdisplay). You can try to set PVDEVICES in /etc/sysconfig/geninitrd." fi if [ "$LVMTOOLSVERSION" = "2" ]; then findmodule "-dm-mod" elif [ "$LVMTOOLSVERSION" = "1" ]; then findmodule "-lvm" findmodule "-lvm-mod" else die "LVM version $LVMTOOLSVERSION is not supported yet." fi debug "LVM v$LVMTOOLSVERSION enabled" have_lvm=yes return fi } firmware_install_module() { local module="$1" local firmware_files="$2" local force="$3" debug "Adding Firmwares ($firmware_files) to initrd for module $module" # firmware not yet installed if [ ! -f "$DESTDIR/lib/firmware/firmware.sh" ]; then inst_d /lib/firmware cat << 'EOF' >> "$DESTDIR/lib/firmware/firmware.sh" #!/bin/sh -e echo 1 > /sys$DEVPATH/loading cat "/lib/firmware/$FIRMWARE" > /sys$DEVPATH/data echo 0 > /sys$DEVPATH/loading exit 0 EOF chmod 755 "$DESTDIR/lib/firmware/firmware.sh" fi for firmware in $firmware_files; do if [ ! -f "/lib/firmware/$firmware" ]; then if [ -n "$force" ]; then die "firmware file /lib/firmware/$firmware doesn't exist." else warn "firmware file /lib/firmware/$firmware doesn't exist. Skipping." fi else inst /lib/firmware/$firmware /lib/firmware/$firmware fi done mount_sys echo "echo -n "/lib/firmware/firmware.sh" > /proc/sys/kernel/hotplug" | add_linuxrc } modules_install() { local modules="$1" local mod for mod in $modules; do MODULEDIR=${mod%/*} inst_d "/lib/modules/$kernel/$MODULEDIR" cp -a "/lib/modules/$kernel/$mod" "$DESTDIR/lib/modules/$kernel/$mod" gunzip "$DESTDIR/lib/modules/$kernel/$mod" 2> /dev/null done } modules_add_linuxrc() { local mod modpath for mod in "$@"; do # module path without optional compression modpath=${mod%.gz} # name of the module module=${modpath##*/} module=${module%$modext} options=$(modprobe_conf | awk -vmodule="$module" '{ if ($1 == "options" && $2 == module) { for(i=3;i<=NF;i++) printf("%s ",$i); }}' | xargs) generic_module=$(echo $module | tr - _) sleep_var=$(eval echo \$MODULE_${generic_module}_USLEEP) firmware_var=$(eval echo \$MODULE_${generic_module}_FIRMWARE) if [ -n "$verbose" ]; then s="" if [ "$options" ]; then s="$s with options [$options]" fi if [ "$sleep_var" ]; then s="$s and $sleep_var usleep" fi debug "Loading module [$module]$s" fi if [ -n "$firmware_var" ]; then firmware_install_module "$module" "$firmware_var" "force=yes" else firmware_files=$(find_firmware "$module") if [ -n "$firmware_files" ]; then for file in $firmware_files; do firmware_install_module "$module" "$file" done fi fi echo "$insmod /lib/modules/$kernel/$modpath $options" | add_linuxrc if [ -n "$sleep_var" ]; then echo "usleep $sleep_var" | add_linuxrc fi done } find_modules_suspend() { if [ ! -x /usr/${_lib}/suspend/resume -a ! -x /usr/sbin/resume ]; then die "/usr/${_lib}/suspend/resume is missing!" fi resume_dev="$(awk '/^resume device =/ { print $4 } ' /etc/suspend.conf)" local vgvolumes=$VGVOLUMES find_modules_for_devpath $resume_dev if [ "$VGVOLUMES" != "$vgvolumes" ]; then # save our VG to be able to differenciate between rootfs VG SUSPENDVG=$VGVOLUMES VGVOLUMES=$vgvolumes debug "suspend device is on LVM" fi } initrd_gen_suspend() { mknod $DESTDIR/dev/snapshot c 10 231 mkdir -p $DESTDIR${resume_dev%/*} inst $resume_dev $resume_dev inst /etc/suspend.conf /etc/suspend.conf if [ -x /usr/${_lib}/suspend/resume ]; then inst /usr/${_lib}/suspend/resume /bin/resume else inst /usr/sbin/resume /bin/resume fi add_linuxrc <<-'EOF' resume=no for arg in $CMDLINE; do if [ "${arg##resume=}" != "${arg}" ]; then resume=yes fi done if [ "$resume" = "yes" ]; then resume fi EOF } initrd_gen_tuxonice() { mount_sys add_linuxrc <<-'EOF' resume=no for arg in $CMDLINE; do if [ "${arg##resume=}" != "${arg}" -o "${arg##resume2=}" != "${arg}" ]; then resume=yes fi done if [ "$resume" = "yes" ]; then [ -e /proc/suspend2/do_resume ] && echo > /proc/suspend2/do_resume [ -e /sys/power/suspend2/do_resume ] && echo > /sys/power/suspend2/do_resume [ -e /sys/power/tuxonice/do_resume ] && echo > /sys/power/tuxonice/do_resume fi EOF } initrd_gen_v86d() { debug "initrd_gen_v86d" mknod $DESTDIR/dev/mem c 1 1 mknod $DESTDIR/dev/tty1 c 4 1 inst_d /sbin inst_exec /sbin/v86d /sbin } initrd_gen_udev() { debug "Setting up udev..." inst_d /sbin /etc/udev if [ ! -x /sbin/initrd-udevd ]; then die "/sbin/initrd-udevd not present" fi inst /sbin/initrd-udevd /sbin/udevd inst /etc/udev/udev.conf /etc/udev/udev.conf mount_dev mount_sys add_linuxrc <<-'EOF' : 'Starting udev' /sbin/udevd --daemon EOF inst /sbin/initrd-udevadm /sbin/udevadm ln -s udevadm $DESTDIR/sbin/udevsettle ln -s udevadm $DESTDIR/sbin/udevtrigger add_linuxrc <<-'EOF' /sbin/udevtrigger /sbin/udevsettle EOF busybox_applet killall add_linuxrc <<-'EOF' killall udevd EOF } initrd_gen_multipath() { inst_d /sbin /lib/udev /etc/multipath inst_exec /sbin/kpartx /sbin inst_exec /sbin/multipath /sbin # for udev callouts inst_exec /sbin/scsi_id /lib/udev inst_exec /sbin/mpath* /sbin egrep -v '^([ ]*$|#)' /etc/multipath.conf > $DESTDIR/etc/multipath.conf if [ -f /etc/multipath/bindings ]; then egrep -v '^([ ]*$|#)' /etc/multipath/bindings > $DESTDIR/etc/multipath/bindings else touch $DESTDIR/etc/multipath/bindings fi mount_dev initrd_gen_devices mount_sys echo "export MPATH_WWID=$MPATH_WWID" | add_linuxrc add_linuxrc <<-'EOF' # parse mpath_wwid= from kernel commandline for arg in $CMDLINE; do if [ "${arg##mpath_wwid=}" != "${arg}" ]; then MPATH_WWID=${arg##mpath_wwid=} if [ "$MPATH_WWID" = "*" ]; then # '*' would mean activate all WWID-s MPATH_WWID= echo "multipath: Activating all WWID-s" else echo "multipath: Activating WWID=$WWID" fi fi done debugshell /sbin/multipath -v 0 $MPATH_WWID for a in /dev/mapper/*; do [ $a = /dev/mapper/control ] && continue /sbin/kpartx -a -p p $a done debugshell EOF } initrd_gen_dmraid() { if [ ! -x /sbin/dmraid-initrd ]; then die "/sbin/dmraid-initrd is missing!" fi inst_d /sbin inst /sbin/dmraid-initrd /sbin/dmraid mount_dev mount_sys initrd_gen_devices add_linuxrc <<-EOF # 2 secs was enough for my system to initialize. but really this is udev issue? usleep 2000000 : 'Activating Device-Mapper RAID(s)' /sbin/dmraid -ay -i debugshell EOF } initrd_gen_bootsplash() { local target="$1" debug "Generating bootsplash" if [ ! -x /bin/splash.bin ]; then warn "Failed to execute /bin/splash.bin. Is bootsplash package installed?" return fi if [ -r /etc/sysconfig/bootsplash ]; then . /etc/sysconfig/bootsplash fi if [ -z "$THEME" ]; then warn "Please configure your /etc/sysconfig/bootsplash first." warn "Generating bootsplashes skipped." return fi if [ -z "$BOOT_SPLASH_RESOLUTIONS" ]; then warn "No BOOT_SPLASH_RESOLUTIONS specified in /etc/sysconfig/bootsplash." warn "Not adding bootsplash to initrd." fi for res in $BOOT_SPLASH_RESOLUTIONS; do if [ -f "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg" ]; then /bin/splash.bin -s -f "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg" >> "$target" && \ debug "Added $res $THEME theme to initrd." else warn "/etc/bootsplash/themes/$THEME/config/bootsplash-$res.cfg doesn't exist, skipped" fi done } initrd_gen_fbsplash() { debug "Generating fbsplash" if [ ! -x /usr/bin/splash_geninitramfs -a ! -x /usr/sbin/splash_geninitramfs ]; then warn "Failed to find splash_geninitramfs. Is splashutils package installed?" return fi splash_geninitramfs_bin=/usr/sbin/splash_geninitramfs [ -f /usr/bin/splash_geninitramfs ] && splash_geninitramfs_bin=/usr/bin/splash_geninitramfs if [ -r /etc/sysconfig/fbsplash ]; then . /etc/sysconfig/fbsplash fi if [ -z "$SPLASH_THEME" ]; then warn "Please configure your /etc/sysconfig/fbsplash first." warn "Generating fbsplashes skipped." return fi if [ -z "$FB_SPLASH_RESOLUTIONS" ]; then warn "No FB_SPLASH_RESOLUTIONS specified in /etc/sysconfig/fbsplash." warn "Not adding fbsplash to initramfs." return fi for res in $FB_SPLASH_RESOLUTIONS; do if [ -f "/etc/splash/$SPLASH_THEME/$res.cfg" ]; then $splash_geninitramfs_bin -c $DESTDIR -r $res $SPLASH_THEME && \ debug "Added $res $SPLASH_THEME theme to initramfs." else warn "/etc/splash/$SPLASH_THEME/$res.cfg doesn't exist, skipped" fi done } initrd_gen_fbcondecor() { debug "Generating fbcondecor" if [ ! -x /usr/bin/splash_geninitramfs -a ! -x /usr/sbin/splash_geninitramfs ]; then warn "Failed to find splash_geninitramfs. Is splashutils package installed?" return fi splash_geninitramfs_bin=/usr/sbin/splash_geninitramfs [ -f /usr/bin/splash_geninitramfs ] && splash_geninitramfs_bin=/usr/bin/splash_geninitramfs if [ -r /etc/sysconfig/splash ]; then . /etc/sysconfig/splash fi if [ -z "$SPLASH_THEME" ]; then warn "Please configure your /etc/sysconfig/splash first." warn "Generating of splashes skipped." return fi if [ -z "$FB_SPLASH_RESOLUTIONS" ]; then warn "No FB_SPLASH_RESOLUTIONS specified in /etc/sysconfig/splash." warn "Not adding fbcondecor to initramfs." return fi for res in $FB_SPLASH_RESOLUTIONS; do if [ -f "/etc/splash/$SPLASH_THEME/$res.cfg" ]; then $splash_geninitramfs_bin -c $DESTDIR -r $res $SPLASH_THEME && \ debug "Added $res $SPLASH_THEME theme to initramfs." else warn "/etc/splash/$SPLASH_THEME/$res.cfg doesn't exist, skipped" fi done } # Generates /dev nodes based on /proc/partitions information. # Needs /proc mounted. # Can be called multiple times. initrd_gen_devices() { if is_yes "$proc_partitions"; then return fi proc_partitions=yes mount_dev add_linuxrc <<-'EOF' : 'Making device nodes' cat /proc/partitions | ( # ignore first two lines: header, empty line read b; read b while read major minor blocks dev rest; do node=/dev/$dev mkdir -p ${node%/*} [ -e $node ] || mknod $node b $major $minor done ) EOF } initrd_gen_md() { debug "Setting up mdadm..." if [ ! -x /sbin/mdadm -o ! -x /sbin/initrd-mdassemble ]; then die "/sbin/mdadm or /sbin/initrd-mdassemble is missing!" fi inst /sbin/initrd-mdassemble /bin/mdassemble # LVM on RAID case dev_list_extra=$(awk '/^DEVICE / { for (i=2; i<=NF; i++) { printf "%s ", $i; }; } ' /etc/mdadm.conf) if [ "$dev_list_extra" = "partitions" ]; then # FIXME: handle this case (see man mdadm.conf) echo "DEVICE partitions" >> "$DESTDIR/etc/mdadm.conf" dev_list_extra="" else for ex_dev in $dev_list_extra; do echo "DEVICE $ex_dev" >> "$DESTDIR/etc/mdadm.conf" done fi do_md0=1 for nr in `seq 1 $rootdev_nr`; do eval cr_rootdev="\$rootdev${nr}" eval cr_dev_list="\$dev_list${nr}" debug echo "Setting up array ($cr_rootdev = $cr_dev_list)" [ "$cr_rootdev" = "/dev/md0" ] && do_md0=0 echo "DEVICE $cr_dev_list" >> "$DESTDIR/etc/mdadm.conf" cr_dev_list_md="$(echo "$cr_dev_list" | xargs | awk ' { gsub(/ +/,",",$0); print $0; }')" cr_md_conf=$(/sbin/mdadm --detail --brief --config=/etc/mdadm.conf $cr_rootdev | awk ' { gsub(/spares=[0-9]+/, "", $0); print $0; }') if [ -n "$cr_md_conf" ]; then echo "$cr_md_conf" >> "$DESTDIR/etc/mdadm.conf" else echo "ARRAY $cr_rootdev devices=$cr_dev_list_md" >> "$DESTDIR/etc/mdadm.conf" fi for f in $cr_dev_list $cr_rootdev $dev_list_extra; do # mkdir in case of devfs name inst_d $(dirname $f) [ -e "$DESTDIR/$f" ] && continue # this works fine with and without devfs inst $f $f done done echo "mdassemble" | add_linuxrc # needed to determine md-version if [ "$do_md0" -eq 1 ]; then mknod $DESTDIR/dev/md0 b 9 0 fi } initrd_gen_nfs() { # use root=/dev/ram0 init=/linuxrc when starting kernel or you will # have problems like init(XX) being child process of swapper(1). debug "Adding rootfs on NFS support to initrd (dhcp)" mknod "$DESTDIR/dev/urandom" c 1 9 mkdir "$DESTDIR/newroot" add_linuxrc <<-'EOF' ifconfig lo 127.0.0.1 up route add -net 127.0.0.0 mask 255.0.0.0 lo ifconfig eth0 up udhcpc -i eth0 -f -q -s /bin/setdhcp cd /newroot pivot_root . initrd [ -x /sbin/chroot ] && exec /sbin/chroot . /sbin/init -i < dev/console > dev/console 2>&1 exec /usr/sbin/chroot . /sbin/init -i < dev/console > dev/console 2>&1 EOF cat <<-'EOF' > "$DESTDIR/bin/setdhcp" #!/bin/sh [ "$1" != "bound" ] && exit [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" [ -n "$subnet" ] && NETMASK="netmask $subnet" ifconfig $interface $ip $BROADCAST $NETMASK up if [ -n "$router" ]; then for r in $router; do route add default gw $r dev $interface done fi for o in $CMDLINE; do case $o in nfsroot=*) rootpath=${o#nfsroot=} ;; esac done if [ -n "$rootpath" ]; then mount -n -t nfs -o ro,nolock,posix,tcp,wsize=8192,rsize=8192 $rootpath /newroot else echo "Missing rootpath in what DHCP server sent to us. Failing..." echo "All seen variables are listed below:" set fi EOF chmod 755 "$DESTDIR/bin/setdhcp" } initrd_gen_lvm() { debug "Adding LVM support to initrd" inst_d /tmp /newroot inst /sbin/initrd-lvm /bin/lvm.static # always make /dev on tmpfs for LVM2 if [ "$LVMTOOLSVERSION" = "2" ]; then mount_dev fi if ! is_yes "$dev_mounted"; then inst_d /dev/mapper mknod $DESTDIR/dev/mapper/control c 10 63 for device in $PVDEVICES; do # if LVM on RAID then device might be copied already in gen_md [ -e "$DESTDIR/dev/$(basename $device)" ] && continue inst $device /dev done fi mount_tmp if [ "$LVMTOOLSVERSION" = "1" ]; then add_linuxrc <<-EOF lvm vgscan -T for vg in $VGVOLUMES; do lvm vgchange -T -a y $vg done EOF else echo "cat /etc/lvm.conf > /tmp/lvm.conf" | add_linuxrc echo "global {" > "$DESTDIR/etc/lvm.conf" echo " locking_type = 0" >> "$DESTDIR/etc/lvm.conf" echo " locking_dir = \"/tmp\"" >> "$DESTDIR/etc/lvm.conf" echo "}" >> "$DESTDIR/etc/lvm.conf" echo "devices {" >> "$DESTDIR/etc/lvm.conf" echo " sysfs_scan=0" >> "$DESTDIR/etc/lvm.conf" if is_yes "$have_md"; then echo " md_component_detection = 1" >> "$DESTDIR/etc/lvm.conf" fi if is_yes "$have_dmraid" || is_yes "$have_multipath"; then echo ' types = [ "device-mapper", 254 ]' >> "$DESTDIR/etc/lvm.conf" fi if [ "$lvm_ignore_devices" ]; then # TODO: think of merging with lvm dumpconfig output echo ' filter = [' >> "$DESTDIR/etc/lvm.conf" local dev for dev in $lvm_ignore_devices; do debug "LVM v2: ignore device $dev" printf ' "r|^%s.*|",\n' $dev done >> "$DESTDIR/etc/lvm.conf" echo ']' >> "$DESTDIR/etc/lvm.conf" fi # XXX filter= must be on one line! lvm dumpconfig | awk '/filter=/' >> "$DESTDIR/etc/lvm.conf" echo "}" >> "$DESTDIR/etc/lvm.conf" initrd_gen_devices add_linuxrc <<-EOF export ROOTDEV=$rootdev export ROOTVG="$VGVOLUMES" export SUSPENDVG=$SUSPENDVG EOF add_linuxrc <<-'EOF' # parse rootdev from kernel commandline if [ "$ROOT" != "$ROOTDEV" ]; then ROOTDEV=$ROOT echo "LVM: Using 'root=$ROOTDEV' from kernel commandline" local tmp=${ROOTDEV#/dev/} if [ "$tmp" != "$ROOTDEV" ]; then ROOTVG=${tmp%/*} echo "LVM: Using Volume Group '$ROOTVG' for rootfs" fi fi # skip duplicate VG if [ "$SUSPENDVG" = "$ROOTVG" ]; then export VGVOLUMES="$ROOTVG" else export VGVOLUMES="$SUSPENDVG $ROOTVG" fi # disable noise from LVM accessing devices that aren't ready. read printk < /proc/sys/kernel/printk if [ ! "$DEBUGINITRD" ]; then echo 0 > /proc/sys/kernel/printk fi export LVM_SYSTEM_DIR=/tmp : 'Scanning for Volume Groups' lvm.static vgscan --mknodes --ignorelockingfailure 2>/dev/null : 'Activating Volume Groups' for vol in $VGVOLUMES; do lvm.static vgchange --ignorelockingfailure -a y $vol 2>/dev/null done echo "$printk" > /proc/sys/kernel/printk # Find out major/minor attrs="$(lvm.static lvdisplay --ignorelockingfailure -c $ROOTDEV 2>/dev/null)" if [ "$attrs" ]; then majmin="${attrs#*$ROOTDEV*:*:*:*:*:*:*:*:*:*:*:*}" if [ "$majmin" != "$attrs" ]; then major="${majmin%:*}" minor="${majmin#*:}" fi fi if [ "$major" -a "$minor" ]; then # Pass it to kernel echo $((256 * $major + $minor)) > /proc/sys/kernel/real-root-dev else echo 2>&1 "Error figuring out real root device for $ROOTDEV!" echo 2>&1 "System will not most likely boot up! So dropping you to a shell!" echo 2>&1 "" sh fi EOF fi } initrd_gen_blkid() { debug "Adding BLKID support to initrd" inst /sbin/initrd-blkid /bin/blkid initrd_gen_devices add_linuxrc <<-'EOF' # if built with blkid change ROOT=LABEL=something into ROOT=/dev/somethingelse - # parsed by blkid if [ "${ROOT##LABEL=}" != "${ROOT}" -o "${ROOT##UUID=}" != "${ROOT}" ]; then ROOT="$(/bin/blkid -t $ROOT -o device -l)" fi EOF } initrd_gen_setrootdev() { debug "Adding rootfs finding based on kernel cmdline root= option support." add_linuxrc <<-'EOF' if [ "${ROOT##/dev/}" != "${ROOT}" ]; then rootnr="$(busybox awk -v rootnode="${ROOT##/dev/}" '$4 == rootnode { print 256 * $1 + $2 }' /proc/partitions)" if [ -n "$rootnr" ]; then echo "$rootnr" > /proc/sys/kernel/real-root-dev fi fi EOF } # main() if [ "$(id -u)" != 0 ]; then die "You need to be root to generate initrd" fi if [ -f /etc/udev/udev.conf -a -x /sbin/initrd-udevd ]; then USE_UDEV=yes . /etc/udev/udev.conf fi if [ -x /sbin/dmraid-initrd ]; then USE_DMRAID=yes fi if [ -x /sbin/multipath ]; then USE_MULTIPATH=yes fi if [ -x /sbin/initrd-blkid ]; then USE_BLKID=yes fi if [ -r /etc/sysconfig/geninitrd ]; then . /etc/sysconfig/geninitrd fi if [ ! -x /bin/initrd-busybox ]; then die "/bin/initrd-busybox is missing!" fi # backwards compatible if [ "$USE_SUSPEND2" ]; then USE_TUXONICE=$USE_SUSPEND2 warn "USE_SUSPEND2 is deprecated, use USE_TUXONICE now instead." fi while [ $# -gt 0 ]; do case $1 in --fstab=*) fstab=${1#--fstab=} ;; --fstab) fstab=$2 shift ;; --modules-conf=*) modulefile=${1#--modules-conf=} ;; --modules-conf) modulefile=$2 shift ;; --use-raidstart|--with-raidstart) USERAIDSTART=yes ;; --without-raidstart) USERAIDSTART=no ;; --use-insmod-static|--with-insmod-static) USEINSMODSTATIC=yes ;; --without-insmod-static) USEINSMODSTATIC=no ;; --with-bootsplash) BOOT_SPLASH=yes ;; --without-bootsplash) BOOT_SPLASH=no ;; --with-fbsplash) FB_SPLASH=yes ;; --without-fbsplash) FB_SPLASH=no ;; --with-fbcondecor) FB_CON_DECOR=yes ;; --without-fbcondecor) FB_CON_DECOR=no ;; --with-suspend) USE_SUSPEND=yes ;; --without-suspend) USE_SUSPEND=no ;; --with-suspend2 | --with-tuxonice) USE_TUXONICE=yes ;; --without-suspend2 | --without-tuxonice) USE_TUXONICE=no ;; --lvmtoolsversion=|--lvmversion=) LVMTOOLSVERSION=${1#--lvmtoolsversion=} LVMTOOLSVERSION=${1#--lvmversion=} ;; --lvmtoolsversion|--lvmversion) LVMTOOLSVERSION=$2 shift ;; --without-udev) USE_UDEV=no ;; --with-udev) USE_UDEV=yes ;; --without-dmraid) USE_DMRAID=no ;; --without-multipath) USE_MULTPATH=no ;; --without-blkid) USE_BLKID=no ;; --with=*) BASICMODULES="$BASICMODULES ${1#--with=}" ;; --with) BASICMODULES="$BASICMODULES $2" shift ;; --version) echo "$PROGRAM: version $VERSION" exit 0 ;; -v) verbose=-v ;; --nocompress) COMPRESS=no ;; --ifneeded) ifneeded=1 ;; -f) force=1 ;; --preload=*) PREMODS="$PREMODS ${1#--preload=}" ;; --preload) PREMODS="$PREMODS $2" shift ;; --fs=*) warn "Warning: --fs option is obsoleted. Use --initrdfs instead" INITRDFS=${1#--fs=} ;; --fs) warn "Warning: --fs option is obsoleted. Use --initrdfs instead" INITRDFS=$2 shift ;; --initrdfs=*) INITRDFS=${1#--initrdfs=} ;; --initrdfs) INITRDFS=$2 shift ;; --image-version) img_vers=yes ;; --ide-only-root) ide_only_root="yes" ;; *) if [ -z "$target" ]; then target="$1" elif [ -z "$kernel" ]; then kernel="$1" else usage fi ;; esac shift done if [ -z "$target" -o -z "$kernel" ]; then usage fi if [ ! -f /boot/vmlinuz-"$kernel" ]; then warn "/boot/vmlinuz-$kernel doesn't exist, is your /boot mounted?" fi pack_version=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d",$1,$2)}') pack_version_long=$(echo "$kernel" | awk -F. '{print sprintf("%03d%03d%03d",$1,$2,$3)}') if [ -z "$INITRDFS" ]; then if [ -z "$FS" ]; then # default value if [ "$pack_version" -ge "002005" ]; then INITRDFS="initramfs" else INITRDFS="rom" fi else warn "Warning: FS configuration options is obsoleted. Use INITRDFS instead" INITRDFS="$FS" fi fi if [ "$pack_version" -lt "002006" ]; then USE_UDEV=no USE_DMRAID=no fi if [ "$pack_version" -ge "002005" ]; then modext=".ko" insmod="insmod" fi if is_yes "$USEINSMODSTATIC"; then insmod="insmod.static" INSMOD="/sbin/insmod.static" if [ "$pack_version" -lt "002005" -a -f /sbin/insmod.static.modutils ]; then INSMOD="/sbin/insmod.static.modutils" fi if [ ! -f "$INSMOD" ]; then die "insmod.static requested but /sbin/insmod.static not found!" fi fi case "$INITRDFS" in ext2) if [ ! -x /sbin/mke2fs ]; then die "/sbin/mke2fs is missing" fi ;; rom|romfs) if [ ! -x /sbin/genromfs ]; then die "/sbin/genromfs is missing" fi ;; cram|cramfs) if [ ! -x /sbin/mkcramfs ]; then die "/sbin/mkcramfs is missing" fi ;; initramfs) if [ ! -x /bin/cpio ]; then die "/bin/cpio is missing" fi if [ ! -x /usr/bin/find ]; then die "/usr/bin/find is missing" fi ;; *) die "Filesystem $INITRDFS on initrd is not supported" ;; esac if [ -L "$target" ]; then target=$(readlink -f "$target") fi if [ -n "$img_vers" ]; then target="$target-$kernel" fi if [ -z "$force" -a -f "$target" ]; then die "$target already exists." fi if [ ! -d "/lib/modules/$kernel" ]; then die "/lib/modules/$kernel is not a directory." fi if [ "$INITRDFS" != "initramfs" ]; then if is_yes "$FB_SPLASH"; then warn "Using fbsplash requires INITRDFS=initramfs; skipping fbsplash generation" FB_SPLASH=no fi if is_yes "$FB_CON_DECOR"; then warn "Using fbcondecor requires INITRDFS=initramfs; skipping fbcondecor generation" FB_CON_DECOR=no fi fi if is_yes "$USE_SUSPEND" && is_yes "$USE_TUXONICE"; then warn "Tuxonice and mainline suspend are exclusive!" fi if is_yes "$FB_SPLASH" && is_yes "$BOOT_SPLASH"; then warn "bootsplash and fbsplash are exclusive!" fi if [ ! -f /proc/mounts ]; then warn "WARNING: /proc filesystem not mounted, may cause wrong results or failure." fi if [ -d /usr/lib64 ]; then _lib=lib64 else _lib=lib fi debug "Using libdir: $_lib" cache_modprobe_conf for n in $PREMODS; do findmodule "$n" done if [ "$FBMODULE" ]; then findmodule "$FBMODULE" fi # allow forcing loading SCSI and/or IDE modules if is_yes "$ADDSCSI"; then find_modules_scsi fi if is_yes "$ADDIDE"; then find_modules_ide fi if is_yes "$USE_SUSPEND"; then find_modules_suspend fi find_root "$fstab" || exit debug "Using $rootdev as device for rootfs" find_modules_for_devpath "$rootdev" [ -n "$rootdev_add" ] && find_modules_for_devpath "$rootdev_add" findmodule "-$rootFs" for n in $BASICMODULES; do findmodule "$n" done if is_yes "$USE_TUXONICE"; then findmodule "-lzf" fi if is_yes "$FB_SPLASH"; then findmodule "-evdev" fi if [ -n "$ifneeded" -a -z "$MODULES" ]; then debug "No modules are needed -- not building initrd image." exit 0 fi DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed" RCFILE="$DESTDIR/linuxrc" > "$RCFILE" chmod a+rx "$RCFILE" ln -s linuxrc $DESTDIR/init # create dirs that we really need inst_d /{lib,bin,etc,dev{,/pts,/shm},loopfs,var,proc,sys} modules_install "$MODULES" # mknod'ing the devices instead of copying them works both with and # without devfs... mknod "$DESTDIR/dev/console" c 5 1 mknod "$DESTDIR/dev/null" c 1 3 mknod "$DESTDIR/dev/zero" c 1 5 inst /bin/initrd-busybox /bin/initrd-busybox ln -s initrd-busybox $DESTDIR/bin/sh ln -s initrd-busybox $DESTDIR/bin/busybox # for older busyboxes who had /bin/busybox as EXEPATH if is_yes "$USEINSMODSTATIC"; then inst "$INSMOD" /bin/insmod.static fi add_linuxrc <> "$RCFILE" # echo "mount -t $loopFs $loopDev /loopfs" >> "$RCFILE" # echo "echo Setting up loopback device $rootdev" >> $RCFILE # echo "losetup $rootdev /loopfs$loopFile" >> "$RCFILE" #fi if is_yes "$USE_UDEV"; then initrd_gen_udev fi if is_yes "$USE_TUXONICE"; then initrd_gen_tuxonice fi if is_yes "$need_v86d"; then initrd_gen_v86d fi if is_yes "$have_dmraid"; then initrd_gen_dmraid fi if is_yes "$have_multipath"; then initrd_gen_multipath fi if is_yes "$USE_BLKID"; then initrd_gen_blkid fi if is_yes "$have_nfs"; then initrd_gen_nfs elif is_yes "$USERAIDSTART" && is_yes "$have_md"; then initrd_gen_md if is_yes "$have_lvm"; then initrd_gen_lvm else initrd_gen_setrootdev fi elif is_yes "$have_lvm"; then initrd_gen_lvm else initrd_gen_setrootdev fi if is_yes "$USE_SUSPEND"; then initrd_gen_suspend fi # additional devs always needed [ ! -e "$DESTDIR/$rootdev_add" ] && inst $rootdev_add /dev if [ "$INITRDFS" = "initramfs" ]; then inst_d /newroot if [ "$rootdev" = "/dev/nfs" ]; then echo "rootfs on NFS root=/dev/nfs" else [ ! -e "$DESTDIR/$rootdev" ] && inst $rootdev /dev fi # Parsing root parameter # We support passing root as hda3 /dev/hda3 0303 0x0303 and 303 add_linuxrc <<-'EOF' device=/dev/no_partition_found eval "$(busybox awk -v c="$ROOT" ' BEGIN { num_pattern_short = "[0-9a-f][0-9a-f][0-9a-f]"; num_pattern = "[0-9a-f]" num_pattern_short; dev_pattern = "[hms][a-z][a-z]([0-9])+"; partition = "no_partition_found"; min = -1; maj = -1; sub("^0x", "", c); if (c ~ "^" num_pattern_short "$") sub("^", "0", c); if (c ~ "^" num_pattern "$") { maj = sprintf("%s",substr(c,1,2)); min = sprintf("%s",substr(c,3)); } if (c ~ "^\/dev\/" dev_pattern "$") sub("^/dev/","", c); if (c ~ "^" dev_pattern "$") partition = c; } $4 ~ partition { maj = $1; min = $2; } $1 ~ maj && $2 ~ min { partition = $4; } END { print sprintf("device=/dev/%s\nmaj=%s\nmin=%s", partition, maj, min); } ' /proc/partitions)" if [ "$device" != '/dev/no_partition_found' -a ! -b $device ]; then mknod $device b $maj $min fi EOF add_linuxrc <<-EOF rootdev=$rootdev rootfs=$rootFs EOF add_linuxrc <<-'EOF' if [ "$device" = '/dev/no_partition_found' ]; then device=$rootdev fi mount -t $rootfs -r $device /newroot init="$(echo "$CMDLINE" | busybox awk '/init=\// { gsub(/.*init=/,NIL,$0); gsub(/ .*/,NIL,$0); print }')" if [ -z "$init" -o ! -x "/newroot$init" ]; then init=/sbin/init fi EOF umount_all busybox_applet switch_root add_linuxrc <<-'EOF' exec switch_root /newroot $init echo "Error! initramfs should not reach this place." echo "It probably means you've got old version of busybox, with broken" echo "initramfs support. Trying to boot anyway, but won't promise anything." exec chroot /newroot $init echo "Failed to chroot!" EOF # we need /init being real file, not symlink, otherwise the initramfs will # not be ran by pid 1 which is required for switch_root mv $DESTDIR/linuxrc $DESTDIR/init ln -s init $DESTDIR/linuxrc else # other than initramfs umount_all fi if is_yes "$FB_SPLASH"; then initrd_gen_fbsplash fi if is_yes "$FB_CON_DECOR"; then initrd_gen_fbcondecor fi IMAGE=$(mktemp -t initrd.img-XXXXXX) || die "mktemp failed" debug "Creating $INITRDFS image $IMAGE" case "$INITRDFS" in ext2) IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}') debug "ext2 image size: $IMAGESIZE ($DESTDIR)" if [ "$IMAGESIZE" -gt 4096 ]; then warn "Your image size is larger than 4096, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!" fi dd if=/dev/zero of="$IMAGE" bs=1k count="$IMAGESIZE" 2> /dev/null mke2fs -q -F -b 1024 -m 0 "$IMAGE" 2>/dev/null 1>&2 tune2fs -i 0 "$IMAGE" >/dev/null 2>&1 local tmpmnt=$(mktemp -d -t initrd.mnt-XXXXXX) debug "Mounting ext2 image $IMAGE to $tmpmnt" mount -o loop -t ext2 "$IMAGE" "$tmpmnt" # We don't need this directory, so let's save space rm -rf "$tmpmnt"/lost+found debug "Copy recursively $DESTDIR -> $tmpmnt" cp -a $DESTDIR/* $tmpmnt umount "$IMAGE" rmdir "$tmpmnt" ;; rom|romfs) genromfs -f "$IMAGE" -d "$DESTDIR" -V "PLD initrd for kernel $kernel" IMAGESIZE=$(stat -c %s $IMAGE | awk '{print int((($1/1024)+1023)/1024)*1024}') debug "Image size for romfs: ${IMAGESIZE}KiB ($IMAGE)" if [ "$IMAGESIZE" -gt 4096 ]; then warn "Your image size is larger than 4096, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!" fi ;; cram|cramfs) mkcramfs "$DESTDIR" "$IMAGE" ;; initramfs) (cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE") ;; *) echo "Filesystem $INITRDFS not supported by $PROGRAM"; esac if is_yes "$COMPRESS"; then tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed" debug "Compressing $target" gzip -9 < "$IMAGE" > "$tmp" mv -f "$tmp" "$target" else cp -a "$IMAGE" "$target" fi # XXX. check if bootsplash can output data to tmp dir not directly to initramfs image. if is_yes "$BOOT_SPLASH"; then initrd_gen_bootsplash "$target" fi rm -rf "$DESTDIR" "$IMAGE" # vim:ts=4:sw=4:noet:fdm=marker