diff options
Diffstat (limited to 'initramfs/initrd-stuff/init')
-rwxr-xr-x | initramfs/initrd-stuff/init | 527 |
1 files changed, 527 insertions, 0 deletions
diff --git a/initramfs/initrd-stuff/init b/initramfs/initrd-stuff/init new file mode 100755 index 00000000..55ee6de9 --- /dev/null +++ b/initramfs/initrd-stuff/init @@ -0,0 +1,527 @@ +#!/bin/sh +# main script for new type of initial ramdisk for OpenSLX linux diskless +# clients version 4 +# +# Dirk von Suchodoletz <dirk@goe.net>, 07-09-2006 +# +# (c) 2006 - RZ Universitaet Freiburg +# (c) 2006 - OpenSLX.ORG project + +# functions common for all distros, messages contains all error and info +# output +. /etc/messages +. /etc/functions || ( echo -e $init_mff && exit 1 ) +. /etc/distro-functions || ( echo -e $init_dff && exit 1 ) +# configuration settings (several file and directory variables) +. /etc/sysconfig/config || ( echo -e $init_dscf && exit 1 ) + +export PATH=/bin:/sbin:/usr/bin/:/usr/sbin +export date="@@@DATE@@@" + +export DEBUGLEVEL=0 +export KERNEL="@@@KERNVER@@@" +export NWMODULES="@@@NWMODULES@@@" +export DISTRO="@@@DISTRO@@@" + +# do not use dnbd cache file +nodnbdcache="yes" + +# device files get their own filesystem (to be move mounted later) +DEVDIR="/dev" +mount -n -t tmpfs -o 'size=25%,mode=0755' initramfsdevs ${DEVDIR} + +# copy basic device files into dev (later udev will handle that) +cp -a /tmp/null /tmp/console /dev +mkdir -p ${DEVDIR}/pts +mkdir -p ${DEVDIR}/shm +mkdir -p ${DEVDIR}/.udevdb + +# mount the important standard directories +[ ! -f /proc/cpuinfo ] && mount -n -t proc proc /proc +echo 256 > /proc/sys/kernel/real-root-dev +[ ! -d /sys/class ] && mount -n -t sysfs sysfs /sys + +# redirect console (after /dev/console is available, and /dev mounted) +exec < /dev/console > /dev/console 2>&1 + +# set defaults for some important variables, might be overwritten via +# kernel commandline +TMPFSSIZE="50%" +COWSIZE="50%" +RWDIR=/dev/shm +NFSRO="nfs" + +# run pre init script and user defined preinit.local, copied by mkdxsinitrd +# from /var/lib/openslx/config/... in stage2 +preinit +[ -x /bin/preinit.local ] && /bin/preinit.local + +# start device auto discovery service - distro specific function +udev_hotplug + +# switch off the several configuration methods, will be switched on +# according to kernel commandline settings +echo "noldap" > /tmp/ldap-done +echo "nodhcp" > /tmp/dhcp-done +echo "nofile" > /tmp/file-done +# read kernel commandline +read KCMDLINE < /proc/cmdline +export KCMDLINE +for opts in ${KCMDLINE} ; do + case ${opts} in + # localization + country=*) + COUNTRY=${opts#country=} + echo -e "\n# localization information gotten via kernel command line \ +in $0\ncountry=\"${COUNTRY}\"" >> /etc/machine-setup + ;; + # single token for debugging ... + debug) + DEBUGLEVEL=1;; + # ... or a specified debug level + debug=*) + DEBUGLEVEL=${opts#debug=} + # Handle empty, extremly large or non-numeric input + [ -z "$DEBUGLEVEL" ] && DEBUGLEVEL=0 + [ $DEBUGLEVEL -eq 8 ] && echo "** SLX init started near $(sysup)" + ;; + # if configuration should be gathered by dhcp client + dhcp) + DHCP="yes" + rm /tmp/dhcp-done + ;; + # if ldap configuration should be triggered + ldap) + LDAP="yes" + rm /tmp/ldap-done + ;; + # ldap configuration with host and port to contact (base) + ldap=*) + LDAP="yes" + rm /tmp/ldap-done + ;; + # if (external, via tftp) configuration file retrieval should be + # triggered, if no source is given try dhcp server and predefined + # standard path (~/tftpboot/client-conf/ ...) + file) + FILE="yes" + rm /tmp/file-done + ;; + # file source with tftp server and file location on the server + file=*) + FILE="yes" + FILESRC=${opts#file=} + rm /tmp/file-done + ;; + # if ld.so.cache should not be generated + noldsc) + NOLDSC=yes;; + # additional source to unify root filesystem with + union=*) + UNIONFS=1 + UNIONDIRS=${opts#union=} + ;; + # if unionfs should be used over the complete root filesystem + unionfs) + UNIONFS=1;; + # if cowloop should be used, only ontop of network block device and in + # combination with classical fs, like ext2 useful + cowloop=*) + COWLOOP=1 + #COWSIZE=${opts#cowloop=} + ;; + # rootfs will void the variables (d)nbdroot, nfsroot ... + # fixme: allow multiple rootfs sources to be unioned!? + # if strinstr " " "$ROOTFS" ... + rootfs=*) + ROOTFS=${opts#rootfs=} + srvproto=$(uri_token $ROOTFS prot) + case $srvproto in + nfs) + NFSROOT=$(uri_token $ROOTFS server)":/"$(uri_token $ROOTFS path) + echo -e "\n# nfs root information gotten via kernel command \ +line in $0\nnfsroot=\"${NFSROOT}\"\n" >> /etc/machine-setup + ;; + *nbd) + nbdmod=$srvproto + # get settings for nbd-client, filesystem equals to path in URI + # notation + nbdhost=$(uri_token $ROOTFS server) + nbdport=$(uri_token $ROOTFS port) + nbdrfst=$(uri_token $ROOTFS path) + ;; + aoe) + echo "Not implemented yet" + ;; + iscsi) + echo "Not implemented yet" + ;; + esac + ;; + # size of cache dnbd should use within ram + dcsize=*) + DNBDCACHESIZE=${opts#dcsize=};; + # ip configuration client-ip:server-ip:gateway:netmask + ip=*) + IPINFO=${opts#ip=};; + # deprecated: nfs server and path (will be removed soon) + nfsroot=*) + NFSROOT=${opts#nfsroot=} + echo -e "\n# nfs root information gotten via kernel command line in $0\n\ +nfsroot=\"${NFSROOT}\"\n" >> /etc/machine-setup + ;; + # size of tempfs if not max. 50% of RAM should be used + tmpfssize=*) + TMPFSSIZE=${opts#tmpfssize=};; + # vendor code identifier for dhcp requests, that way odlx clients could + # be distinguished from other (dhcp) clients + vci=*) + VCI=${opts#vci=};; + esac +done +# check if at least one type of IP configuration is availabe +if [ -z "$DHCP" -a -z "$LDAP" -a -z "$IPINFO" ] ; then + echo -e "# You did not specify any advanced configuration mode for your \ +clients. You\n# might want to add the token 'dhcp' for DHCP configuration, \ +'file(=source)'\n# for config file get via TFTP or 'ldap(=source)' for LDAP \ +configuration to\n# your kernel command line." >> /etc/machine-setup + if strinfile "clientip" /etc/machine-setup ; then + # IP configuration seems to be present in machine-setup file + . /etc/machine-setup + IPINFO="ip=$clientip:$serverip:$gateway:$subnet_mask" + else + error "$init_errip" + fi +fi +# for ldap configuration at least basic IP setup is needed to contact the +# server +[ -z "$DHCP" -a -n "$LDAP" -a -z "$IPINFO" ] && error "$init_errldap" +# set debug level and logfile +echo "Setting debuglevel to ${DEBUGLEVEL}" +export MODPRV=" " +export LOGFILE +if [ "${DEBUGLEVEL}" -gt 0 -a "${DEBUGLEVEL}" != 8 ] ; then + # if LOGFILE should be used within initial ramdisk add '/mnt' in front + # of the variable + LOGFILE="/var/log/dxs-boot.log" + echo "1 4 1 7" >/proc/sys/kernel/printk + [ "${DEBUGLEVEL}" -ge 2 ] && MODPRV="-v" + [ "${DEBUGLEVEL}" -gt 3 ] && { + set -x + # and the kernel too + echo "7 7 7 7" >/proc/sys/kernel/printk; } + [ "${DEBUGLEVEL}" -gt 10 ] && set +x +else + # switch off most of kernel debug output + echo "0 0 0 0" >/proc/sys/kernel/printk + # modprobe should stay quiet + MODPRV="-q" + LOGFILE="/dev/null" +fi +# load network adaptor modules +for mod in ${NWMODULES}; do + modprobe ${MODPRV} $mod || error "$init_errnwad" +done +# set up loopback networking (ipsetup - function defined in /etc/functions) +ipsetup 127.0.0.1 255.0.0.0 0.0.0.0 127.255.255.255 lo +# analyze ip information from the kernel command line and put parts +# of it into several variables +if [ -n "$IPINFO" ] ; then + getip () { + val=$IPINFO; i=$(expr $1 - 1); + while [ $i -gt 0 ] ; do + val=${val#*:} ; i=$(expr $i - 1); + done; + echo $val|sed "s/:.*//"; } + clientip=$(getip 1) + serverip=$(getip 2) + gateway=$(getip 3) + subnet_mask=$(getip 4) + echo -e "# ip configuration written by $0 script\nclientip=$clientip\n\ +subnet_mask=$sub_netmask\ngateway=$gateway\nserverip=$serverip" \ + >>/etc/machine-setup + # set static ip address via function ipsetup + ipsetup $clientip $subnet_mask $gateway 255.255.255.255 eth0 +else + noipyet="yes" +fi +# get configuration data via dhcp (with vendor code identifier if present +# in ${VCI} (from kernel command line) ... +[ -n "$DHCP" ] && rundhcp ${VCI} & +if [ -n "$noipyet" ] ; then + waitfor /tmp/dhcp-done 20000 + . /etc/machine-setup + [ -f /tmp/confviadhcp ] && . /tmp/confviadhcp + [ -z "$clientip" -o -z "$subnet_mask" -o -z "$gateway" \ + -o -z "$broadcast_address" ] && error "$init_errdhcp" + ipsetup $clientip $subnet_mask $gateway $broadcast_address eth0 +fi +# ... or ldap if available (in background) +[ -n "$LDAP" ] && ldapconf & +# ... or via tftp file get (in background) +[ -n "$FILE" ] && fileget & + +# if root filesystem should be imported via (d) network block device +if [ -n "${nbdmod}" ] ; then + # load block device driver if needed + modprobe ${MODPRV} ${nbdmod} || error "$init_errnbd" + [ -z "$nbdrfst" ] && nbdrfst=ext2 + echo "Diskless client using ${nbdmod} on $nbdhost:$nbdport with $nbdrfst" + # fixme: check for fs in /proc/filesystems before trying to load the module + modprobe ${MODPRV} ${nbdrfst} || error "$init_errnbd" nonfatal + + case "${nbdmod}" in + # network block device present in standard kernel + nbd) + RDEV=/dev/nbd0 + waitfor "${RDEV}" 30000 || error "$init_nbddev" + echo "0" > /sys/block/nbd0/queue/read_ahead_kb + nbd-client $nbdhost $nbdport ${RDEV} || error "$init_nbdcl" + usleep 10 + # switch off unneeded block read ahead + echo "0" > /sys/block/nbd0/queue/read_ahead_kb + ;; + # dnbd by Thorsten Zitterell + dnbd) + if [ -z $nodnbdcache ] ; then # variable not really used yet + mkdir /dnbd + mount -n -o 'size=10%' -t tmpfs tmpfs /dnbd + ( cat /dev/zero > /dnbd/cache 2>/dev/null || echo "ok" >/tmp/cache ) & + clientopt="-c /dnbd/cache" + waitfor /tmp/cache 10000 + fi + waitfor /dev/dnbd0 10000 || error "$init_nbddev" + while ! dnbd-client -b $nbdhost -d /dev/dnbd0 $clientopt ; do + usleep 20 + done + echo "0" > /sys/block/dnbd0/queue/read_ahead_kb + RDEV=/dev/dnbd0 + ;; + esac + RWRO="ro" + if [ -n "${COWLOOP}" -a -x /bin/cowdev ] ; then + modprobe ${MODPRV} cowloop || { + error "$init_loadcow" nonfatal + COWLOOP=""; } + fi + if [ -n "${COWLOOP}" ] ; then + if [ -n "${UNIONFS}" ] ; then + error "$init_cownonbd" + UNIONFS=""; + fi + echo "Using Copy-on-Write block device for rw access" + mount -n -t tmpfs -o size=${COWSIZE} ramfs ${RWDIR} + mkdir /dev/cow && cp -a /tmp/ctl /dev/cow + usleep 10 + ln -s /dev/cowloop0 /dev/cow/0 + cowdev -a /dev/nbd0 ${RWDIR}/nbd.cow + usleep 10 + RWRO="rw" + RDEV=/dev/cow/0 + # run ldconfig if not switched off via kernel command line + ldcfg + else + # use normal UnionFS behaviour because rootfs is not NFS + NFSRO="" + fi + # finally mount the block device + for i in 5 40 60 ; do + usleep $i + mount -n -t $nbdrfst -o $RWRO $RDEV /mnt 2>/dev/null && break + done +fi + +# if no type of root filesystem is passed via kernel command line try +# information gathered from dhcp process +if [ -z "${nbdmod}" -a -z "${nbdhost}" -a -z "${NFSROOT}" ] ; then + # information has to be read from dhcp configuration + if [ -z "$noipyet" ] ; then + waitfor /tmp/dhcp-done 20000 + fi + waitfor /tmp/ldap-done 20000 + . /etc/machine-setup + NFSROOT=${serverip}:${root_path} +fi +# call function for nfs mounts +if [ -z "${nbdmod}" -a -z "${nbdserver}" ] ; then + nfsmnt ${NFSROOT} || error "$init_nfs" +fi + +# get the complete collection of kernel modules available +mount -n --bind /mnt/lib/modules/${KERNEL} /lib/modules/${KERNEL} || \ + error "$init_moddir" +# start hardware configuration as background process +hwautocfg & + +# try to use unionfs for rw access if available +if [ -n "${UNIONFS}" -o -n "${UNION}" ] ; then + modprobe ${MODPRV} unionfs || { + error "$init_loadufs" nonfatal + UNIONFS=""; } +fi + + +# setup of client root filesystem dependent on the availability of UnionFS +if [ -n "${UNIONFS}" ] ; then + echo "Using UnionFS for rw access" + mkdir -p ${RWDIR}/union ${RWDIR}/uniontmp /rorootfs + mount -n -t tmpfs none ${RWDIR}/uniontmp + # hack for handling unionfs with patched run-init + mount -n --move /mnt /rorootfs + mount -n -t unionfs -o dirs=${RWDIR}/uniontmp:/rorootfs=${NFSRO}ro \ + none /mnt + mkdir -p /mnt/uniontmp + mount -n --move ${RWDIR}/uniontmp /mnt/uniontmp + # if additional sources should be used for a combined root filesystem + # probably more sources should be merged into union (${UNION} is defined) + # allow more than one union?? + if [ -n "${UNION}" ] ; then + # for dir in "${UNION}"; do + # testmkd /unionadd/$dir + # mount $dir unionadd/$dir + # unionctl mnt --add --after /mnt --mode ro /unionadd/$dir + # most probably it is a good idea to run ldconfig, so enable it + unset NOLDSC + fi + # run ldconfig if not switched off via kernel command line + ldcfg +elif [ -z "$COWLOOP" ] ; then + echo "Using bind mounts to ramdisk for rw access" + mount -n -t tmpfs -o size=${TMPFSSIZE} ramfs ${RWDIR} + for path in ${D_BINDMPTS} ; do + mkdir -p ${RWDIR}/${path} >/dev/null 2>&1 + mount -n --bind ${RWDIR}/${path} /mnt/${path} + [ ${DEBUGLEVEL} -gt 1 -a ${DEBUGLEVEL} != 8 ] && \ + echo "Created ${RWDIR}/${path} and mounted it to /mnt/$path" + done + # see above ... + ldcfg + # Save the RO Directories mentioned in the distro-specific + # config to a temporary directory. They will lateron be restored + for path in ${D_RODIRSINRW}; do + if [ -d /mnt/${path} ] ; then + LIST=${path}" "$LIST + # exclude them from etc copy process too + echo ${path}|sed -e "s,/root/,," >>/tmp/etc.exclude + mkdir -p /root/${path} >/dev/null 2>&1 + mount -n --bind /mnt/${path} /root/${path} >/dev/null 2>&1 + fi + done + for path in /etc/${D_SYSCONFDIR} ${D_DIRINBINDMNT} ${LIST}; do + mkdir -p ${RWDIR}/${path} + done + testmkd ${RWDIR}/var/tmp + chmod a+rwxt ${RWDIR}/var/tmp >/dev/null 2>&1 + echo -e "${D_ETCEXCL} @@@COMETCEXCL@@@" >>/tmp/etc.exclude + # if ld.so.cache is to be generated then do not copy the file + [ -z "${NOLDSC}" ] && echo -e "ld.so.cache*" >>/tmp/etc.exclude + # for tar exclude lists might be used, more difficult for cp + cd /mnt + tar -X /tmp/etc.exclude -cp etc/* | \ + tar -xp -C ${RWDIR} 2>/dev/null ; + cd / + mount -n --bind ${RWDIR}/etc /mnt/etc + mount -n --bind ${RWDIR}/var /mnt/var + # get the "covered" mounts back into filesystem structure + for i in ${LIST}; do + mount -n --move /root/$i /mnt/$i #>>$LOGFILE 2>&1 + done + #rm -rf /root/* >/dev/null 2>&1 + # run some specific stuff !? +fi +# script for stuff to execute during early bootup +d_mkrlscript init boot.ld "Running configuration postponed from InitRD" +echo "fs complete" >/tmp/fscmpl + +# write debug file information after filesystem setup completed +echo -e "# /etc${D_SYSCONFDIR}/logfile - file created by $0 (initramfs \ +from $date)\n#\n# logfile \ +for linux diskless client specific debugging output\nLOGFILE=\"$LOGFILE\"\n#\ +\n# debug level\nDEBUGLEVEL=\"$DEBUGLEVEL\"" \ + > /mnt/etc/${D_SYSCONFDIR}/logfile || error "$init_errlog" + +# run distribution independent and dependent configuration of files and +# services +servconfig & + +for path in @@@COMDIRINDXS@@@ ${D_DIRINDXS} ${D_DIRINBINDMNT} ; do + testmkd /mnt/${path} +done +# Needed writable subdirs nested in readonly subdirs of writable one +for path in ${D_RWDIRSINRO}; do + mount -n -t tmpfs none /mnt/${path} +done +for i in /var/run/utmp /var/log/wtmp /var/log/lastlog /etc/mtab ; do + echo -n > /mnt/$i +done +chmod a+rwxt /mnt/tmp /mnt/tmp/scratch 2>/dev/null & +chown 65534:0 /mnt/var/lib/nobody & +echo -e "# /etc/fstab - file generated by $0 (initramfs from $date)\n#\ +\tDirk von \ +Suchodoletz, dirk@goe.net\n\nrootfs\t\t/\t\trootfs\t\tro\t\t 0 0\n\ +proc\t\t/proc\t\tproc\t\tdefaults\t 0 0\ninitramdevs\t/dev\t\ttmpfs\ +\t\trw\t\t 0 0\ndevpts\t\t/dev/pts\tdevpts\t\tmode=0620,gid=5\t 0 0\n\ +usbfs\t\t/proc/bus/usb\tusbfs\t\tnoauto\t\t 0 0" >/mnt/etc/fstab || \ + error "$init_fstab" +echo -e "rootfs / rootfs rw 0 0\ninitramdevs /dev tmpfs rw\ + 0 0" > /mnt/etc/mtab + +# copy library cache if generated +if [ -z "${NOLDSC}" ] ; then + if waitfor /tmp/ldcfg 50000 ; then + test -s /mnt/tmp/ld.so.cache && { + cp /mnt/tmp/ld.so.cache /mnt/etc/ld.so.cache + rm /mnt/tmp/ld.so.cache; } + else + error "$init_errldcfg" + fi +else + error "$init_infldcfg" nonfatal +fi +# copy machine configuration (from global settings, additions made within +# here and from dhcp/ldap sources) to client /etc for later checks +waitfor /tmp/hwcfg 20000 || error "$init_errhw" +waitfor /tmp/svcfg 20000 || error "$init_errsw" +# IP configuration is made and should not be updated automatically, udevd +# should be killed if started within init +killall -9 dhcpcd dhclient pump 2>/dev/null +cp /etc/machine-setup /mnt/etc + +# post init for some distro specific (fixme!! more elegant solution) +postinit +[ -s /initramfs/postinit.local ] && \ + cp /initramfs/postinit.local /bin/postinit.local +[ -x /bin/postinit.local ] && { + echo "Running postinit.local - if boot stops here, check the script!" + /bin/postinit.local; } + +# start a debug shell in higher debug levels +[ $DEBUGLEVEL -gt 2 -a $DEBUGLEVEL != 8 ] && /bin/sh + +# unmount the bind mounted modules directory +for i in 0 40 100 200 300 500 800 1000 1200; do + usleep $i && umount -n /lib/modules/${KERNEL} 2>/dev/null && break + error "$init_wait" nonfatal +done + +[ $i -gt 1000 ] && error "$init_errumnt" +# check for inittab file +test -f /mnt/etc/inittab || error "$init_erritab" +# close runlevel script for stuff to execute during early bootup +d_mkrlscript close boot.ld "" +# put /tmp into stage4 mtab +sed -n "s,/mnt,,;/\/tmp /p" /proc/mounts >> /mnt/etc/mtab +# preparations to leave initrd - umounting ... +umount -n /sys || error "$init_errsys" nonfatal +umount -n /proc/bus/usb >/dev/null 2>&1 +mount -n --move /dev /mnt/dev +killall -9 udevd 2>/dev/null +[ $DEBUGLEVEL -eq 8 ] && echo "** SLX init ended near $(sysup)" +umount -n /proc +# unset old environment variables +unset debug date initrd ip dnbdroot nbdroot nfsroot vci vga +unset BOOT_IMAGE KCMDLINE KERNEL MODPRV NWMODULES OLDPWD UDEVD_EVENT_TIMEOUT \ + UDEVD_EXPECTED_SEQNUM +#strinstr "bash" "$(ls -la /bin/sh)" && EE="-c" +# new style of pivoting (exec -c would set an empty environment in bash) +exec run-init -c dev/console /mnt /sbin/init || error "$init_runinit" |