#!/bin/bash ################################################################################ # Mknfsinitrd Creates an initial ramdisk image for NFS boot # T.Barnaby, BEAM Ltd, 14/2/04 # Some functions taken from /sbin/mkinitrd ################################################################################ # modulesPreload="nfs e1000e igb fscache" busyboxProgs="[ ash awk basename bunzip2 bzcat cat chgrp chmod\ chown chroot chvt clear cmp cp cut date dd deallocvt\ df dirname dmesg du echo egrep env expr false fgrep\ find free grep gunzip gzip halt head hexdump hostid hostname\ id ifconfig init insmod install ipaddr kill killall klogd\ linuxrc ln logger ls lsmod mkdir mknod mkswap mktemp\ modprobe more mount mv openvt pidof ping pivot_root poweroff\ ps pwd readlink reboot reset rm rmdir rmmod route sed\ sh sleep sort strings swapoff swapon sync syslogd tail\ tar tee test time touch tr true tty udhcpc umount uname uniq\ unzip uptime usleep vi wc wget which whoami xargs yes\ zcat stat switch_root" baseDir="" kernelVersion="" modules="" verbose="-v" target="" builtins="" ############################################################################## # Script files ############################################################################## # fileInit(){ cat <<"EOF" #!/bin/sh ################################################################################ # Init.rc Diskless NFS boot init script # T.Barnaby, BEAM Ltd, 16/2/05 ################################################################################ # modules="mii pps_core e1000e i2c-core i2c-algo-bit dca igb sunrpc auth_rpcgss nfs_acl fscache lockd nfs" echo "BEAM Diskless boot starting ..." #mount -n -o remount,rw / mount -n -t proc /proc /proc mount -n -t sysfs none /sys mount -n -t tmpfs /dev/shm /tmp #/bin/sh echo "Loading modules" for m in $modules; do insmod /lib/$m.ko done #/bin/sh echo "Seting up network interface" while true; do if udhcpc -s /dhcpConfig -f -n -q -i eth0; then break; fi if udhcpc -s /dhcpConfig -f -n -q -i eth1; then break; fi done . /tmp/dhcpInfo if [ -n "$dhcp_hostname" ]; then hostname $dhcp_hostname fi #/bin/sh echo "Mounting root filesystem" mount -n -t rpc_pipefs sunrpc /var/lib/nfs/rpc_pipefs mount -n -r -t nfs -o async,nolock $dhcp_rootpath /sysroot #/bin/sh echo "Switching to new root" echo 0x100 > /proc/sys/kernel/real-root-dev umount /var/lib/nfs/rpc_pipefs umount /sys umount /proc umount /tmp echo "Doing switch_root" exec switch_root /sysroot /sbin/init #exec switch_root /sysroot /bin/sh EOF } fileDhcpConfig(){ cat <<"EOF" #!/bin/sh ################################################################################ # dhcpConfig Sets up network interface # T.Barnaby, BEAM Ltd, 16/2/05 ################################################################################ # configureNetwork(){ ifconfig $interface $ip if [ -n "$router" ]; then route add default gw $router fi echo "dhcp_interface=$interface" > /tmp/dhcpInfo echo "dhcp_ip=$ip" >> /tmp/dhcpInfo echo "dhcp_mask=$mask" >> /tmp/dhcpInfo echo "dhcp_subnet=$subnet" >> /tmp/dhcpInfo echo "dhcp_broadcast=$broadcast" >> /tmp/dhcpInfo echo "dhcp_router=$router" >> /tmp/dhcpInfo echo "dhcp_dns=$dns" >> /tmp/dhcpInfo echo "dhcp_namesvr=$namesvr" >> /tmp/dhcpInfo echo "dhcp_hostname=$hostname" >> /tmp/dhcpInfo echo "dhcp_domain=$domain" >> /tmp/dhcpInfo echo "dhcp_siaddr=$siaddr" >> /tmp/dhcpInfo echo "dhcp_rootpath=$rootpath" >> /tmp/dhcpInfo echo "dhcp_timesvr=$timesvr" >> /tmp/dhcpInfo echo "dhcp_ntpsrv=$ntpsrv" >> /tmp/dhcpInfo echo "dhcp_tftp=$tftp" >> /tmp/dhcpInfo echo "dhcp_timezone=$timezone" >> /tmp/dhcpInfo echo "dhcp_logsvr=$logsvr" >> /tmp/dhcpInfo echo "dhcp_swapsvr=$swapsvr" >> /tmp/dhcpInfo } case $1 in deconfig) ifconfig $interface 0.0.0.0;; bound) configureNetwork;; esac exit 0 EOF } ############################################################################## # Functions ############################################################################## # moduledep() { if [ ! -f "$baseDir/lib/modules/$kernelVersion/modules.dep" ]; then echo "No dep file found for kernel $kernelVersion" >&2 exit 1 fi [ -n "$verbose" ] && echo -n "Looking for deps of module $1" deps=$(awk 'BEGIN { searched=ARGV[2]; ARGV[2]=""; rc=1 } \ function modname(filename) { match(filename, /([^\/]+)\.k?o:?$/, ret); return ret[1] } \ function show() { if (orig == searched) { print dep; orig=""; rc=0; exit } } \ /^.*/ { show(); \ orig=modname($1); dep=""; \ if ($2) { for (i = 2; i <= NF; i++) { dep=sprintf("%s %s", dep, modname($i)); } } } \ /^ / { dep=sprintf("%s %s", dep, modname($1)); } \ END { show(); exit(rc) }' $baseDir/lib/modules/$kernelVersion/modules.dep $1) [ -n "$verbose" ] && echo -e "\t$deps" } findmodule() { skiperrors="" echo "FindModule: $1" if [ $1 == "--skiperrors" ]; then skiperrors=--skiperrors shift fi local modName=$1 if [ "$modName" = "off" -o "$modName" = "null" ]; then return fi if [ $(echo $modName | cut -b1) = "-" ]; then skiperrors=--skiperrors modName=$(echo $modName | cut -b2-) fi if echo $builtins | egrep -q '(^| )'$modName'( |$)' ; then [ -n "$verbose" ] && echo "module $modName assumed to be built in" set +x return fi # special cases if [ "$modName" = "i2o_block" ]; then findmodule i2o_core findmodule -i2o_pci modName="i2o_block" elif [ "$modName" = "ppa" ]; then findmodule parport findmodule parport_pc modName="ppa" elif [ "$modName" = "sbp2" ]; then findmodule ieee1394 findmodule ohci1394 modName="sbp2" elif [ "$modName" = "igb" ]; then findmodule pps_core findmodule i2c-core findmodule i2c-algo-bit findmodule dca modName="igb" else moduledep $modName for i in $deps; do findmodule $i done fi for modExt in o.gz o ko ; do if [ -d $baseDir/lib/modules/$kernelVersion/updates ]; then fmPath=`(cd $baseDir/lib/modules/$kernelVersion/updates; echo find . -name $modName.$modExt -type f | /bin/awk {'print $1; exit;'}` fi if [ -f $baseDir/lib/modules/$kernelVersion/updates/$fmPath ]; then fmPath=updates/$fmPath break fi fmPath=`(cd $baseDir/lib/modules/$kernelVersion; find . -name $modName.$modExt -type f) | /bin/awk {'print $1; exit;'}` if [ -f $baseDir/lib/modules/$kernelVersion/$fmPath ]; then break fi done if [ ! -f $baseDir/lib/modules/$kernelVersion/$fmPath ]; then if [ -n "$skiperrors" ]; then return fi # ignore the absence of the scsi modules for n in $PRESCSIMODS; do if [ "$n" = "$modName" ]; then return; fi done; if [ -n "$allowmissing" ]; then echo "WARNING: No module $modName found for kernel $kernelVersion, continuing anyway" >&2 return fi echo "No module $modName found for kernel $kernelVersion, aborting." >&2 exit 1 fi # only need to add each module once if ! echo $modules | grep -q "$fmPath" 2>/dev/null ; then modules="$modules $fmPath" fi } inst() { if [ "$#" != "2" ];then echo "usage: inst <file> <destination>" return fi [ -n "$verbose" ] && echo "cp $1 -> $2" cp $1 $2 } usage () { echo "usage: `basename $0` [-v][-d baseDir] <initrd-image> <kernel-version>" >&2 echo "" >&2 echo " (ex: `basename $0` initrd-2.6.10-1.760_FC3 2.6.10-1.760_FC3)" >&2 exit 1 } ############################################################################## # Main code ############################################################################## # while [ $# -gt 0 ]; do case $1 in -v) verbose=-v ;; -d) shift baseDir=$1 ;; *) if [ -z "$target" ]; then target=$1 elif [ -z "$kernelVersion" ]; then kernelVersion=$1 else usage fi ;; esac shift done echo "BaseDir: $baseDir"; if [ -z "$target" -o -z "$kernelVersion" ]; then usage fi if [ ! -d $baseDir/lib/modules/$kernelVersion ]; then echo "$baseDir/lib/modules/$kernelVersion is not a directory." >&2 exit 1 fi if false; then if [ $UID != 0 ]; then echo "mknfsinitrd must be run as root" exit 1 fi fi # find a temporary directory which doesn't use tmpfs TMPDIR="" for t in /tmp /var/tmp /root ${PWD}; do if [ ! -d $t ]; then continue; fi if ! echo access -w $t; then continue; fi fs=$(df -T $t 2>/dev/null | awk '{line=$1;} END {printf $2;}') if [ "$fs" != "tmpfs" ]; then TMPDIR=$t break fi done if [ -z "$TMPDIR" ]; then echo "no temporary directory could be found" >&2 exit 1 fi if [ $TMPDIR = "/root" -o $TMPDIR = "${PWD}" ]; then echo "WARNING: using $TMPDIR for temporary files" >&2 fi # Add preload modules for n in $modulesPreload; do findmodule $n done if [ -n "$verbose" ]; then echo "Using modules: $modules" fi #echo "TMPDIR: $TMPDIR" #exit 0 ############################################################################## # Main wor ############################################################################## # MNTIMAGE=`mktemp -d ${TMPDIR}/initrd.XXXXXX` IMAGE=`mktemp ${TMPDIR}/initrd.img.XXXXXX` #MNTIMAGE=/tmp/initrd if [ -z "$MNTIMAGE" -o -z "$IMAGE" ]; then echo "Error creating temporaries. Try again" >&2 exit 1 fi echo "MNTIMAGE: $MNTIMAGE" mkdir -p $MNTIMAGE mkdir -p $MNTIMAGE/lib mkdir -p $MNTIMAGE/bin mkdir -p $MNTIMAGE/etc mkdir -p $MNTIMAGE/dev mkdir -p $MNTIMAGE/proc mkdir -p $MNTIMAGE/sys mkdir -p $MNTIMAGE/sysroot mkdir -p $MNTIMAGE/usr mkdir -p $MNTIMAGE/usr/bin mkdir -p $MNTIMAGE/usr/sbin mkdir -p $MNTIMAGE/var mkdir -p $MNTIMAGE/var/lib/nfs/rpc_pipefs mkdir -p $MNTIMAGE/tmp rm -f $MNTIMAGE/sbin ln -s bin $MNTIMAGE/sbin # Install needed programs #inst /sbin/nash "$MNTIMAGE/bin/nash" #inst /sbin/insmod.static "$MNTIMAGE/bin/insmod" #ln -s /sbin/nash $MNTIMAGE/sbin/modprobe #inst /bin/bash $MNTIMAGE/bin #ln -s bash $MNTIMAGE/bin/sh # Test progs if false; then # Install libs inst /lib/libtermcap.so.2 $MNTIMAGE/lib inst /lib/libdl.so.2 $MNTIMAGE/lib inst /lib/libc.so.6 $MNTIMAGE/lib inst /lib/ld-linux.so.2 $MNTIMAGE/lib #inst /sbin/ifconfig $MNTIMAGE/bin/ifconfig1 #inst /bin/dmesg $MNTIMAGE/bin inst /usr/bin/strace $MNTIMAGE/bin #inst /sbin/lsmod $MNTIMAGE/bin fi # Install busybox inst /sbin/busybox-beam $MNTIMAGE/bin/busybox for p in $busyboxProgs; do ln -sf busybox $MNTIMAGE/bin/$p done # Copy modules for m in $modules; do echo "Copy kernel module: $m" if [ -x /usr/bin/strip ]; then /usr/bin/strip -g $baseDir/lib/modules/$kernelVersion/$m -o $MNTIMAGE/lib/$(basename $m) else cp -a $baseDir/lib/modules/$kernelVersion/$m $MNTIMAGE/lib fi done if false; then # Create main devices mknod $MNTIMAGE/dev/console c 5 1 mknod $MNTIMAGE/dev/null c 1 3 mknod $MNTIMAGE/dev/ram b 1 1 mknod $MNTIMAGE/dev/urandom c 1 9 mknod $MNTIMAGE/dev/systty c 4 0 mknod $MNTIMAGE/dev/tty c 5 0 for i in 1 2 3 4; do mknod $MNTIMAGE/dev/tty$i c 4 $i done fi #touch $MNTIMAGE/etc/fstab # Setup udev #inst /sbin/udev.static $MNTIMAGE/sbin/udev #ln -s udev $MNTIMAGE/sbin/udevstart #mkdir -p $MNTIMAGE/etc/udev #inst /etc/udev/udev.conf $MNTIMAGE/etc/udev/udev.conf #ln -s /sbin/nash $MNTIMAGE/sbin/hotplug # Create rc script filea fileInit > $MNTIMAGE/init fileDhcpConfig > $MNTIMAGE/dhcpConfig chmod +x $MNTIMAGE/init chmod +x $MNTIMAGE/dhcpConfig (cd $MNTIMAGE; find . | cpio --quiet -c -o) > $IMAGE gzip -9 < $IMAGE > $target || rc=1 rm -rf $MNTIMAGE $IMAGE exit 0