# based on mkinitrd from RedHat Linux
#
-RCSID='$Id$'
-R=${RCSID#* * }; VERSION=${R%% *}
+RCSID='$Revision$ $Date$'
+R=${RCSID#* *}; VERSION=${R%% *}
PROGRAM=${0##*/}
. /etc/rc.d/init.d/functions
# list of geninitrd modules which need setup routine after commandline args parsing
GENINITRD_MODS=""
COMPRESS=yes
-# it should be safe to remove scsi_mod from here, but I'm not sure...
-PRESCSIMODS="-scsi_mod unknown -sd_mod"
target=""
kernel=""
force=""
# are /dev nodes already created from /proc/devices info?
proc_partitions=no
-# whether v86d should be installed
-need_v86d=0
-
-# if we should init NFS at boot
-have_nfs=no
-
usage() {
uname_r=$(uname -r)
echo "usage: $PROGRAM [--version] [-v] [-f] [--ifneeded] [--preload <module>]"
echo " [--with=<module>] [--image-version] [--fstab=<fstab>] [--nocompress]"
+ echo " [--compress=yes|xz|lzma|bzip2|gzip]"
echo " [--initrdfs=rom|initramfs|ext2|cram] [--modules-conf=<modules.conf>]"
- echo " [--with-raidstart] [--without-raidstart]"
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-dmraid]"
+ echo " [--with-multipath=DEVPATH] [--without-multipath]"
echo " [--without-blkid] [--without-luks]"
echo " <initrd-image> <kernel-version>"
echo ""
mknod /dev/console c 5 1
mknod /dev/null c 1 3
mknod /dev/zero c 1 5
+ mknod /dev/urandom c 1 9
mkdir /dev/pts
mkdir /dev/shm
EOF
#
# NB! XXX do not output to STDOUT, it will appear in initrd images in some cases!
busybox_applet() {
- local err=0
+ local err=0 applet
if [ -z "$busybox_functions" ]; then
local tmp=$($busybox 2>&1)
done
if [ $have = 0 ]; then
MODULES="$MODULES $mod"
-
- # if we are adding uvesafb, we need v86d as well
- if [ "$module" = "uvesafb" ]; then
- need_v86d=yes
- fi
fi
done
}
fi
}
-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
- find_module "$mod"
- done
- else
- find_module "$n"
- fi
- done
- find_module "-scsi_wait_scan"
-}
-
# find modules for $devpath
find_modules_for_devpath() {
local devpath="$1"
return
fi
- 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
- find_module "$m"
- done
- fi
- find_module "-ipv4"
- find_module "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)."
+ if is_nfs "$devpath"; then
+ find_modules_nfs "$devpath"
return
fi
if find_modules_multipath "$devpath"; then
return
fi
+
# fallback
fi
# fallback
fi
- if is_yes "$(echo "$devpath" | awk '/^\/dev\/(sd|scsi)/ { print "yes"; }')"; then
- find_modules_scsi
+ if is_scsi "$devpath"; then
+ find_modules_scsi "$devpath"
return
fi
fi
for firmware in $firmware_files; do
- if [ ! -f "/lib/firmware/$firmware" ]; then
- die "firmware file /lib/firmware/$firmware doesn't exist."
- else
+ if [ -f "/lib/firmware/$kernel/$firmware" ]; then
+ FIRMWAREDIR=${firmware%/*}
+ [ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
+ inst /lib/firmware/$kernel/$firmware /lib/firmware/$firmware
+ elif [ -f "/lib/firmware/$firmware" ]; then
FIRMWAREDIR=${firmware%/*}
[ "$FIRMWAREDIR" != "$firmware" ] && inst_d /lib/firmware/$FIRMWAREDIR
inst /lib/firmware/$firmware /lib/firmware/$firmware
+ else
+ die "firmware file /lib/firmware/$firmware nor /lib/firmware/$kernel/$firmware found."
fi
done
if [ -n "$sleep_var" ]; then
echo "usleep $sleep_var" | add_linuxrc
fi
- done
-}
+ if [ "$module" = "scsi_wait_scan" ]; then
+ if [ "$(busybox_applet rmmod 2>/dev/null; echo $?)" = 0 ]; then
+ echo "rmmod scsi_wait_scan" | add_linuxrc
+ fi
+ fi
-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
+ done
}
# Generates /dev nodes based on /proc/partitions information.
EOF
}
-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_setrootdev() {
debug "Adding rootfs finding based on kernel cmdline root= option support."
umount_all
busybox_applet switch_root
add_linuxrc <<-'EOF'
- exec switch_root /newroot $init
+ exec switch_root /newroot $init ${1:+"$@"}
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
+ exec chroot /newroot $init ${1:+"$@"}
echo "Failed to chroot!"
EOF
ln -s init $DESTDIR/linuxrc
}
-# main()
-if [ "$(id -u)" != 0 ]; then
- die "You need to be root to generate initrd"
-fi
+# find if $symbol exists in System.map $mapfile
+sym_exists() {
+ local mapfile="$1"
+ local symbol="$2"
+ if [ ! -f $mapfile ]; then
+ # missing mapfile (not a pld kernel?)
+ return 1
+ fi
+
+ awk -vc=1 -vsymbol="$symbol" '$2 == "T" && $3 == symbol {c = 0} END {exit c}' $mapfile
+}
+
+# find best compressor (or forced one) for initrd
+find_compressor() {
+ local mode="$1"
+ # the best compressor list
+ local compressors='xz lzma bzip2 gzip'
+
+ # a specified one, take it
+ if ! is_yes "$mode"; then
+ compressors="$mode"
+ fi
+
+ debug "finding compressor: $compressors (via $mode)"
+ # check for compressor validity
+ local c prog map=/boot/System.map-$kernel
+ for c in $compressors; do
+ case $c in
+ xz)
+ sym=unxz
+ prog=/usr/bin/xz
+ ;;
+ lzma)
+ sym=unlzma
+ prog=/usr/bin/xz
+ ;;
+ bzip2)
+ sym=bzip2
+ prog=/usr/bin/bzip2
+ ;;
+ gzip)
+ sym=gunzip
+ prog=/bin/gzip
+ ;;
+ *)
+ die "Unknown compressor $c"
+ ;;
+ esac
+ if sym_exists $map $sym && [ -x $prog ]; then
+ echo $c
+ return
+ fi
+ done
+
+ debug "using gzip for compressor (fallback)"
+ echo gzip
+}
if [ -r /etc/sysconfig/geninitrd ]; then
. /etc/sysconfig/geninitrd
fi
-geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor
+if [ ! -f /proc/mounts ]; then
+ warn "/proc filesystem not mounted, may cause wrong results or failure."
+fi
+
+geninitrd_load_mods ide luks multipath dmraid lvm md blkid udev tuxonice suspend fbsplash condecor bootsplash uvesafb nfs scsi
while [ $# -gt 0 ]; do
case $1 in
modulefile=$2
shift
;;
- --use-raidstart|--with-raidstart)
- USERAIDSTART=yes
- ;;
- --without-raidstart)
- USERAIDSTART=no
- ;;
--with-bootsplash)
BOOT_SPLASH=yes
;;
USE_DMRAID=no
;;
--without-multipath)
- USE_MULTPATH=no
+ USE_MULTIPATH=no
+ ;;
+ --with-multipath=*)
+ USE_MULTIPATH=${1#--with-multipath=}
;;
--without-blkid)
USE_BLKID=no
-v)
verbose=-v
;;
+ --compress)
+ COMPRESS=$2
+ ;;
+ --compress=*)
+ COMPRESS="${1#--compress=}"
+ ;;
--nocompress)
COMPRESS=no
;;
PREMODS="$PREMODS $2"
shift
;;
- --fs=*)
+ --fs=* | --fs)
die "--fs option is obsoleted. Use --initrdfs instead"
- INITRDFS=${1#--fs=}
- ;;
- --fs)
- die "--fs option is obsoleted. Use --initrdfs instead"
- INITRDFS=$2
- shift
;;
--initrdfs=*)
INITRDFS=${1#--initrdfs=}
exit 1
fi
+# main()
+if [ "$(id -u)" != 0 ]; then
+ die "You need to be root to generate initrd"
+fi
+
if [ -d /usr/lib64 ]; then
_lib=lib64
else
die "/lib/modules/$kernel is not a directory."
fi
-if [ ! -f /proc/mounts ]; then
- warn "/proc filesystem not mounted, may cause wrong results or failure."
-fi
-
if [ "$kernel_version" -ge "002005" ]; then
modext=".ko"
fi
fi
# allow forcing loading SCSI and/or IDE modules
+# XXX: where ADDSCSI cames from? drop?
if is_yes "$ADDSCSI"; then
find_modules_scsi
fi
+# XXX: where ADDIDE cames from? drop?
if is_yes "$ADDIDE"; then
find_modules_ide
fi
find_modules_for_devpath "$rootdev"
+# if USE_MULTIPATH is path to device, scan that too
+# this is to bootstrap multipath setup into initrd.
+if ! is_no "$USE_MULTIPATH" && ! is_yes "$USE_MULTIPATH"; then
+ find_modules_multipath $USE_MULTIPATH
+fi
+
find_module "-$rootFs"
for n in $BASICMODULES; do
exit 0
fi
+debug "Building initrd..."
DESTDIR=$(mktemp -d -t initrd.XXXXXX) || die "mktemp failed"
RCFILE="$DESTDIR/linuxrc"
> "$RCFILE"
mknod "$DESTDIR/dev/console" c 5 1
mknod "$DESTDIR/dev/null" c 1 3
mknod "$DESTDIR/dev/zero" c 1 5
+mknod "$DESTDIR/dev/urandom" c 1 9
inst_exec $busybox /bin/initrd-busybox
ln -s initrd-busybox $DESTDIR/bin/sh
initrd_gen_tuxonice
fi
-if is_yes "$need_v86d"; then
- initrd_gen_v86d
-fi
+find_modules_uvesafb
+initrd_gen_uvesafb
if is_yes "$have_luks"; then
initrd_gen_luks
if is_yes "$have_nfs"; then
initrd_gen_nfs
-elif is_yes "$USERAIDSTART" && is_yes "$have_md"; then
+elif is_yes "$have_md"; then
initrd_gen_md
if is_yes "$have_lvm"; then
initrd_gen_lvm
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
;;
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"
(cd $DESTDIR; find . | cpio --quiet -H newc -o > "$IMAGE")
;;
*)
- echo "Filesystem $INITRDFS not supported by $PROGRAM";
+ die "Filesystem $INITRDFS not supported by $PROGRAM"
esac
-if is_yes "$COMPRESS"; then
+# TODO: figure out this automatically
+CONFIG_BLK_DEV_RAM_SIZE=4096
+
+IMAGESIZE=$(du -ks $DESTDIR | awk '{print int(($1+1023+512)/1024)*1024}')
+debug "image size: $IMAGESIZE KiB ($DESTDIR)"
+if [ "$IMAGESIZE" -gt $CONFIG_BLK_DEV_RAM_SIZE ]; then
+ warn "Your image size is larger than $CONFIG_BLK_DEV_RAM_SIZE, Be sure to boot kernel with ramdisk_size=$IMAGESIZE!"
+fi
+
+if ! is_no "$COMPRESS"; then
tmp=$(mktemp "$target".XXXXXX) || die "mktemp failed"
- debug "Compressing $target"
- gzip -9 < "$IMAGE" > "$tmp"
+ compressor=$(find_compressor "$COMPRESS")
+ debug "Compressing $target with $compressor"
+
+ # TODO: the image name (specified from kernel.spec) already contains
+ # extension, which is .gz most of the time.
+ case "$compressor" in
+ xz)
+ # don't use -9 here since kernel won't understand it
+ xz --format=xz --check=crc32 --lzma2=preset=6e,dict=1MiB < "$IMAGE" > "$tmp"
+ ;;
+ lzma)
+ xz --format=lzma -9 < "$IMAGE" > "$tmp"
+ ;;
+ bzip2)
+ bzip2 -9 < "$IMAGE" > "$tmp"
+ ;;
+ gzip)
+ gzip -9 < "$IMAGE" > "$tmp"
+ ;;
+ esac
mv -f "$tmp" "$target"
else
cp -a "$IMAGE" "$target"
fi
-size=$(stat -c %s $target | awk '{print int((($1/1024)+1023)/1024)*1024}')
-debug "Minimum RAM size that could be used for $target is: ramdisk_size=$size"
-
# 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"