#!/bin/sh # # Simple init script that should handle both # livecd/livedisk, thinclient and hdd boot # PATH=/usr/sbin:/usr/bin:/sbin:/bin INITRAMFSCONF="/etc/initramfs.conf" ROOT_LINKS="bin sbin lib boot usr opt" ROOT_TREES="etc root home var run" TMPFS_DIRS="dev mnt mnt/cdrom mnt/livecd mnt/thin tmp sys proc media" LOOPBACKFILE="/boot/pisi.sqfs" NORESUME=0 LIVE=0 NFSROOT=0 QUIET=0 RAID_INCREMENTAL=1 RAID=0 LVM=0 COPYTORAM=0 SPLASH=0 WIPEMEM=0 HOTPLUG="/sbin/hotplug" MNTDIR="" FS_TYPE="" INITRAMFS="" ROOT_FLAGS="" ROOT_DEVICE="" ROOT_TARGET="" RESUME_DEVICE="" WIPEMEM_OPTS="-llv" ########################### # Miscellaneous functions # ########################### info() { echo "<6>initramfs: $1" > /dev/kmsg } log_output() { $@ | echo "<6>`sed 's#^\(.*\)$#initramfs:\1#g'`" > /dev/kmsg } fall2sh() { # Kill any possible plymouth instances test -x /bin/plymouth && /bin/plymouth quit &> /dev/null kill -9 $(pidof plymouthd) &> /dev/null echo "--> $*" echo "Reboot with initramfs=shell(noprobe) to further debug the issue." # Use a login shell for sourcing /etc/profile /bin/sh -l } run_dhcpc() { udhcpc -C -i eth0 -s /etc/udhcpc.script } ################## # Device probers # ################## probe_devices() { # Set hotplug helper for firmware loading echo $HOTPLUG > /proc/sys/kernel/hotplug if [ "x$1" = "x--with-kms" ]; then probe_kms test -x /bin/plymouth && /bin/plymouth show-splash fi probe_pci_devices probe_virtio_devices probe_usb_devices # Unset hotplug helper echo > /proc/sys/kernel/hotplug [ "${RAID}" -eq "1" ] && probe_raid [ "${LVM}" -eq "1" ] && probe_lvm } probe_kms() { for device in /sys/bus/pci/devices/*/boot_vga; do [ -f $device ] || continue info "Loading KMS driver" grep -q 1 $device && modprobe -bq `cat ${device%boot_vga}modalias` done if [ ! -c /dev/fb0 ]; then echo "options uvesafb scroll=ywrap mtrr=0 nocrtc=1 mode_option=1024x768-32" > /etc/modprobe.d/uvesafb.conf modprobe -bq uvesafb fi } probe_pci_devices() { info "Probing PCI devices" local MODULES="" for module in /sys/bus/pci/devices/*/modalias; do [ -f $module ] || continue MODULES="$MODULES $(cat $module)" done modprobe -bqa $MODULES } probe_usb_devices() { info "Probing USB devices" local MODULES="" for module in /sys/bus/usb/devices/*/modalias; do [ -f $module ] || continue MODULES="$MODULES $(cat $module)" done modprobe -bqa $MODULES } probe_raid() { info "Probing RAID devices" modprobe -bqa dm-mod raid0 raid1 raid10 raid456 if [ -x /sbin/mdadm ] then /sbin/mdadm --examine --scan > /etc/mdadm.conf /sbin/mdadm -As fi } probe_lvm() { info "Probing LVM devices" modprobe -qa dm-mod if [ -x /sbin/lvm ] then /sbin/lvm vgscan --ignorelockingfailure &> /dev/null /sbin/lvm vgchange -ay --sysinit --ignorelockingfailure &> /dev/null /sbin/lvm vgmknodes --ignorelockingfailure &> /dev/null fi } probe_virtio_devices() { local MODULES="" for module in /sys/bus/virtio/devices/*/modalias; do [ -f $module ] || continue MODULES="$MODULES $(cat $module)" done modprobe -bqa $MODULES } ################################# # Filesystem specific functions # ################################# mount_rootfs() { FS_TYPE=`disktype $ROOT_DEVICE | grep KERNELMODULE | awk '{print $2}'` info "Mounting rootfs: $ROOT_DEVICE ($FS_TYPE)" mount -r -t $FS_TYPE -n ${ROOT_FLAGS} ${ROOT_DEVICE} /newroot } find_live_mount() { modprobe -bqa usb-storage udf if [ "$#" -gt "0" ] then for x in $* do # this is used for non Linux fs detection FS_TYPE=`disktype $1 | grep KERNELMODULE | awk '{print $2}'` if [ -n "$FS_TYPE" -a -f /lib/modules/*/$FS_TYPE.ko ] then modprobe $FS_TYPE 1> /dev/null 2>&1 fi mount -r ${x} /newroot/mnt/cdrom > /dev/null 2>&1 if [ "$?" = "0" ] then # Check for cdroot image if [ -e /newroot/mnt/cdrom/${LOOPBACKFILE} ] then ROOT_DEVICE="/newroot${x}" if [ "$COPYTORAM" == "1" ] then info "Copying Live Media files to RAM" mkdir /newroot/mnt/cdromtemp cp -af /newroot/mnt/cdrom/* /newroot/mnt/cdromtemp/ umount /newroot/mnt/cdrom rmdir /newroot/mnt/cdrom mv /newroot/mnt/cdromtemp /newroot/mnt/cdrom fi break else umount /newroot/mnt/cdrom fi fi done fi } manage_tmpfs() { mount -t tmpfs tmpfs /newroot for d in ${TMPFS_DIRS}; do mkdir -p "/newroot/${d}" done } mount_nfs() { FS_LOCATION='mnt/thin' # Change directory to /newroot cd /newroot # FIXME: busybox mount does not load automatically modprobe -q nfs # mount nfs if [ -z "/etc/udhcpc.info" ] then fall2sh "/etc/udhcpc.info not found" fi . /etc/udhcpc.info if [ -z "${ROOTPATH}" ] then fall2sh "NFS rootpath not found" fi echo "Mounting NFS from $ROOTPATH" mount -o tcp,nolock,ro $ROOTPATH /newroot/mnt/thin if [ "$?" != '0' ] then fall2sh "Could not nfs root" fi # Create necessary links for x in ${ROOT_LINKS}; do ln -s "${FS_LOCATION}/${x}" "${x}" done if [ -e "${FS_LOCATION}/lib32" ] then ln -s "${FS_LOCATION}/lib32" "lib32" fi # We need this for x86_64 ln -s "${FS_LOCATION}/lib" "lib64" chmod 1777 tmp (cd /newroot/${FS_LOCATION}; cp -a ${ROOT_TREES} /newroot) # Needed for ltspfs mechanism echo "$IP $HOSTNAME" >> /newroot/etc/hosts } mount_cdroot() { FS_LOCATION="mnt/livecd" # Change directory to /newroot cd /newroot # These are not loaded automatically modprobe -q squashfs # Loop type squashfs mount -t squashfs -o loop,ro /newroot/mnt/cdrom/${LOOPBACKFILE} /newroot/mnt/livecd if [ "$?" != "0" ] then fall2sh "Could not mount root image" fi # Create necessary links for x in ${ROOT_LINKS}; do ln -s "${FS_LOCATION}/${x}" "${x}" done if [ -e "${FS_LOCATION}/lib32" ] then ln -s "${FS_LOCATION}/lib32" "lib32" fi # We need this for x86_64 ln -s "${FS_LOCATION}/lib" "lib64" chmod 1777 tmp (cd /newroot/${FS_LOCATION}; cp -a ${ROOT_TREES} /newroot) # FIXME: the device list is taken from udev, we can't rely on sys entries since pluggable means different # in kernel world. Suggestions that do not include this kind of regexp mania are welcome # for userspace applications REAL_ROOT_TYPE=`echo "${ROOT_DEVICE}" | sed -e 's/^\/newroot\/dev\///' | grep -qE '^sr[0-9]*|^hd[a-z]|^pcd[0-9]|^xvd*' && echo "optical" || echo "harddisk"` echo "${REAL_ROOT_TYPE}" > /newroot/run/pisilinux/livemedia # this is needed for yali MNTDIR=`grep \/mnt\/cdrom\ /proc/mounts|sed 's/\/newroot//g'` echo "$MNTDIR" >> /newroot/etc/fstab } ############################## # Config and cmdline parsers # ############################## # FIXME: maybe we should just source the file instead of parsing # also consider merging conf parser and cmdline parser parse_config() { while read inputline; do case "${inputline}" in raid=*) RAID=$(echo $inputline|cut -f2- -d=) ;; lvm=*) LVM=$(echo $inputline|cut -f2- -d=) ;; thin=*) NFSROOT=$(echo $inputline|cut -f2- -d=) ;; root=*) ROOT_TARGET=$(echo $inputline|cut -f2- -d=) ;; rootflags=*) ROOT_FLAGS=$(echo $inputline|cut -f2- -d=) ;; liveroot=*) # Installation or livecd, enable RAID by default # to be able to read existing RAID installations LIVE=1 RAID_INCREMENTAL=0 LIVEROOT=$(echo $inputline|cut -f2- -d=) ;; resume=*) RESUME_DEVICE="${inputline#resume=}" ;; noresume) NORESUME=1 ;; copytoram) COPYTORAM=1 ;; wipemem) WIPEMEM=1 ;; wipememopts=*) WIPEMEM=1 WIPEMEM_OPTS=$(echo $inputline|cut -f2- -d=) ;; splash) SPLASH=1 ;; init=*) INIT="${inputline#INIT=}" ;; esac done < $INITRAMFSCONF } parse_cmdline() { for x in `cat /proc/cmdline`; do case "${x}" in [0123456Ss]) # Normalize 'S' to 's' LEVEL=`echo ${x}|tr A-Z a-z` ;; mudur=*) for m in `echo ${x}|cut -f2 -d=|sed 's/,/ /g'`; do case "${m}" in livecd) LIVE=1 ;; livedisk) LIVE=1 ;; raid) RAID=1 ;; lvm) LVM=1 ;; thin) NFSROOT=1 ;; esac done ;; initramfs=*) INITRAMFS=`echo ${x}|cut -f2- -d=` ;; root=*) ROOT_TARGET=`echo ${x}|cut -f2- -d=` ;; rootflags=*) ROOT_FLAGS="-o ${x#rootflags=}" ;; liveroot=*) LIVE=1 LIVEROOT=$(echo ${x}|cut -f2- -d=) ;; resume=*) RESUME_DEVICE="${x#resume=}" ;; noresume) NORESUME=1 ;; init=*) INIT="${x#init=}" ;; copytoram) COPYTORAM=1 ;; wipemem) WIPEMEM=1 ;; wipememopts=*) WIPEMEM=1 WIPEMEM_OPTS=$(echo $x|cut -f2- -d=) ;; splash) SPLASH=1 ;; single) LEVEL="s" ;; quiet) QUIET=1 ;; blacklist=*) modules=${x#blacklist=} for module in ${modules//,/ }; do echo "blacklist $module" >> /etc/modprobe.d/cmdline.conf done ;; esac done if [ -f /etc/modprobe.d/cmdline.conf ]; then cp /etc/modprobe.d/cmdline.conf /dev/.modprobe.initramfs.conf fi } #################### # init starts here # #################### info "Starting init on initramfs" # Mount needed filesystems mount -n -t proc proc /proc mount -n -t sysfs sysfs /sys # Added to start udev properly #mkdir -m 0755 /run #mount -t tmpfs tmpfs /run # Prepare /dev (Needs kernel >= 2.6.32) mount -t devtmpfs devtmpfs /dev mkdir -m 0755 /dev/pts mount -t devpts -o gid=5,mode=620 devpts /dev/pts # First parse config file, then cmdline to allow overwriting internal config if [ -f "$INITRAMFSCONF" ] then #. $INITRAMFSCONF parse_config fi # Parse command line parameters parse_cmdline # Minimize printk log test "x$QUIET" = "x1" && echo "1" > /proc/sys/kernel/printk # Initialize plymouth daemon if found and splash is true # Don't even launch plymouthd if we're in single-user mode if [ "$LEVEL" != "s" -a "$SPLASH" = "1" -a -x /sbin/plymouthd ]; then /sbin/plymouthd --attach-to-session fi # Handle initramfs= parameter if [ "${INITRAMFS}" == "shellnoprobe" ] then fall2sh "Starting up a shell without probing" elif [ "${INITRAMFS}" == "shell" ] then probe_devices --with-kms fall2sh "Starting up a shell" fi if [ "${WIPEMEM}" = "1" ] then info "Wiping out memory, system will be shutdown after completion" sdmem ${WIPEMEM_OPTS} poweroff -f fi # Probe devices probe_devices --with-kms if [ -x /usr/sbin/resume -a -b "$RESUME_DEVICE" -a "x$NORESUME" != "x1" ] then if [ "x$SPLASH" == "x1" ] then SPLASHPARAM="-P splash=y" else SPLASHPARAM="-P splash=n" fi # FIXME: This will fail if resume= contains LABEL/UUID info "Attempting to resume from hibernation" /usr/sbin/resume $SPLASHPARAM $RESUME_DEVICE fi echo 0x0100 > /proc/sys/kernel/real-root-dev if [ "${LIVE}" -eq "1" ] then ROOT_DEVICE="" manage_tmpfs # modprobe filesystems that are not in kernel, for live disks modprobe -qa nls_cp857 nls_utf8 vfat for i in `seq 50` do t=`findfs ${LIVEROOT} 2>/dev/null` find_live_mount "$t" if [ "${ROOT_DEVICE}" != "" ] then break else probe_devices usleep 200000 fi done if [ "${ROOT_DEVICE}" == "" ] then fall2sh "Could not find mount media" fi mount_cdroot elif [ "${NFSROOT}" -eq "1" ] then run_dhcpc manage_tmpfs mount_nfs # set hostname for mudur hostname $HOSTNAME else # Wait until ROOT_DEVICE appears for i in `seq 50` do # let findfs handle all conversion ROOT_DEVICE=`findfs ${ROOT_TARGET} 2>/dev/null` if [ ! -b "${ROOT_DEVICE}" ] then probe_devices usleep 200000 else break fi done if [ ! -b "${ROOT_DEVICE}" ] then fall2sh "Could not find boot device" else mount_rootfs fi fi [ "${INIT}" == "" ] && INIT="/sbin/init"; # This stops /lib/udev/rules.d/65-md-incremental.rules from medling with mdraid sets. [ "${RAID_INCREMENTAL}" -eq "0" ] && touch /dev/.in_sysinit # Move mounts instead of umount/mount mount --move /dev /newroot/dev mount --move /proc /newroot/proc mount --move /sys /newroot/sys # Added to start udev properly #mount --move /run /newroot/run # And we start info "Switching to the real root" test -x /bin/plymouth && /bin/plymouth update-root-fs --new-root-dir=/newroot exec /bin/switch_root -c /dev/console /newroot ${INIT} ${LEVEL}