2 # Copyright 2003-2006 Gentoo Foundation
3 # Copyright 2006-2010 Francois Dupoux
4 # Distributed under the terms of the GNU General Public License v2
9 msg_string="${msg_string:-...}"
10 [ "$2" != 1 ] && echo -e "${GOOD}>>${NORMAL} ${msg_string} ${NORMAL}"
16 msg_string="${msg_string:-...}"
17 [ "$2" != 1 ] && echo -e "${BAD}!!${NORMAL} ${msg_string} ${NORMAL}"
24 local key_name="`echo "$1" | cut -f1 -d=`"
25 local key_len=${#key_name}
26 local value_start=$((key_len+2))
27 echo "$1" | cut -c ${value_start}-
32 sysresccd_expand_alldevices()
40 sysresccd_expand_removable()
42 # Look for the value of 1 in the file /sys/block/sd*/removable
45 devroot=$(echo ${curdev} | awk -F / '{sub(/[0-9]+$/,"",$NF); print $NF}')
46 removable_f="/sys/block/${devroot}/removable"
47 [ -f "${removable_f}" ] && grep -q ^1 ${removable_f} && echo ${curdev}
53 if [ -n "$1" ] && [ -x "$1" ]
65 bad_msg "Running a mini shell (cannot complete the boot process)"
70 sysresccd_setup_keymap()
74 if [ ! -e /dev/vc/0 -a ! -e /dev/tty0 ]
77 mount -o bind ${NEWROOT}/dev /dev
79 [ ! -e /dev/tty0 ] && ln -s /dev/tty1 /dev/tty0
81 sysresccd_chooseKeymap
83 [ "${DEVBIND}" -eq '1' ] && umount /dev
84 else # "setkmap=xx" option was used
85 sysresccd_useKeymap $SETKMAP
93 if [ -e /lib/keymaps/${keymap}.map ]
95 good_msg "Loading the ''${keymap}'' keymap"
96 loadkmap < /lib/keymaps/${keymap}.map
98 echo ${keymap} | grep -e "[0-9]+" >/dev/null 2>&1
101 xkeymap=`tail -n 7 /lib/keymaps/keymapList | grep ${keymap} | sed -r "s/.*\s+${keymap}\s+([a-z-]+).*/\1/g" | grep -v 1`
103 mkdir -p /etc/sysconfig
104 echo "XKEYBOARD=${xkeymap}" > /etc/sysconfig/keyboard
105 elif [ "$keymap" = '' ]
108 good_msg "Keeping default keymap"
110 bad_msg "Sorry, but keymap ''${keymap}'' is invalid!"
111 sysresccd_chooseKeymap
115 sysresccd_chooseKeymap()
117 good_msg "Loading keymaps"
118 cat /lib/keymaps/keymapList
119 echo "default choice (US keymap) will be used if no action within 20 seconds"
120 read -t 20 -p '<< Load keymap (Enter for default): ' keymap
121 sysresccd_useKeymap $keymap
126 # set terminal in utf8 mode
128 #/bin/consolechars -f /lat0-sun16.psf
129 #dumpkeys | loadkeys --unicode
134 # Run debug shell if requested with "minishell" in cmdline
135 if [ "${MINISHELL}" = '1' ]
137 good_msg "Running a mini shell (as requested by the command line)"
138 sysresccd_runshell ${MINISHELL}
142 # ---- convert a short netmask (eg: '/24') to a long one ----
143 netmask_shorttolong() # eg: '24' ==> '255.255.255.0'
148 [ "${mask}" -gt '32' ] && mask='32'
149 [ "${mask}" -lt '0' ] && mask='0'
154 for j in 0 1 2 3 4 5 6 7
156 curbit=0 ; [ "$bit" -lt "$mask" ] && curbit=1
157 curbyte=$((curbyte*2))
158 curbyte=$((curbyte+curbit))
162 [ "$i" -lt '3' ] && echo -n '.'
167 # configure an interface: eg: $1='192.168.1.1/24' $2='eth0'
172 ipaddrbase=${ethip%%/*} # '192.168.1.1/24' --> '192.168.1.1'
174 if echo "${ethip}" | grep -q -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/([0-9]{1,2})$'
176 ipaddrmask=${ethip#*/} # '192.168.1.1/24' --> '24'
181 if [ -n "${ipaddrmask}" ]
183 iplongmask=$(netmask_shorttolong $ipaddrmask 2>/dev/null)
184 maskopt="netmask ${iplongmask}"
185 echo "netconfig1: netmask_shorttolong($ipaddrmask)=$iplongmask"
191 echo "netconfig1: configure ${cureth} to ${ethip}"
192 ipcmd_add="ifconfig ${cureth} ${ipaddrbase} ${maskopt}"
193 ${ipcmd_add} ; res=$?
194 echo "netconfig1: ${ipcmd_add} --> ${res}"
199 if [ -n "${SPEAKUP}" ]
201 OPTLIST="$(echo ${SPEAKUP} | sed -e 's!,! !g')"
203 for curopt in ${OPTLIST}
209 SPEAKUP_QUIET=`parse_opt "${x}"`
212 SPEAKUP_SYNTH=`parse_opt "${x}"`
215 SPEAKUP_PORT=`parse_opt "${x}"`
216 SPEAKUP_OPTIONS="${SPEAKUP_OPTIONS} port=${SPEAKUP_PORT}"
219 SPEAKUP_SER=`parse_opt "${x}"`
220 SPEAKUP_OPTIONS="${SPEAKUP_OPTIONS} ser=${SPEAKUP_SER}"
226 if [ -n "${SPEAKUP_QUIET}" ]
228 cmd="modprobe speakup quiet=${SPEAKUP_QUIET}"
232 if [ -n "${SPEAKUP_SYNTH}" ]
234 cmd="modprobe speakup_${SPEAKUP_SYNTH} ${SPEAKUP_OPTIONS} start=1"
240 sysresccd_udev_start()
242 good_msg "Loading modules..."
244 echo '0' > /proc/sys/kernel/printk
246 # Note that this only becomes /dev on the real filesystem if udev's scripts
247 # are used; which they will be, but it's worth pointing out
249 if [ -e /etc/udev/udev.conf ]; then
250 . /etc/udev/udev.conf
252 mount -t tmpfs -o size=$tmpfs_size,mode=0755 udev /dev
253 [ -e /dev/console ] || mknod -m 0600 /dev/console c 5 1
254 [ -e /dev/null ] || mknod /dev/null c 1 3
255 > /dev/.initramfs-tools
256 mkdir /dev/.initramfs
259 export MODPROBE_OPTIONS="-qb"
261 # delete the useless modules
262 ls /lib/modules | grep -v $(uname -r) | busybox xargs rm -rf
264 # process module dependencies
267 # load custom modules
268 for modname in ${MODLOAD}
273 good_msg "modprobe ${modname} successful"
275 bad_msg "modprobe ${modname} failed (res=$?)"
279 # write blacklist to modprobe.d
280 for modname in ${BLACKLIST}
282 echo "blacklist ${modname}" >> /etc/modprobe.d/initramfs
283 good_msg "module ${modname} has been blacklisted"
286 # run udevd and let it process uevents
287 echo > /sys/kernel/uevent_helper
288 mkdir -p /dev/.udev/db/
289 udevd --daemon --resolve-names=never
290 mkdir -p /dev/.udev/queue/ /dev/.udev/rules.d/
292 udevadm settle || true
294 # if the scandelay parameter has been set, we wait a bit for devices
295 sleep 3 # sleep 3 seconds anyway: most USB devices just need it to initialize
296 [ -n "${SCANDELAY}" ] && good_msg "Waiting ${SCANDELAY} seconds..." && sleep ${SCANDELAY}
298 # show list of modules which have been loaded
301 while read modname details
303 [ ${modcount} -ge 1 ] && modlist="${modlist}, "
304 modlist="${modlist}${modname}"
305 modcount=$((modcount+1))
310 sysresccd_udev_stop()
312 # Stop udevd, we'll miss a few events while we run init, but we catch up
313 for proc in /proc/[0-9]*
315 [ -x $proc/exe ] || continue
316 [ "$(busybox readlink $proc/exe)" != /sbin/udevd ] || kill ${proc#/proc/}
318 echo '6' > /proc/sys/kernel/printk
321 sysresccd_netconfig()
323 good_msg "Performing the network configuration..."
325 # ---- force dhcp if booting via pxe and no static configuration specified
326 if [ "${NETCONFIG}" = '1' ] && [ -z "${SETETHX}" ]
331 # ---- create the /etc/nsswitch.conf file (it must exist for both dns and static) ----
332 rm -f /etc/nsswitch.conf /etc/host.conf
333 echo "hosts: files dns" > /etc/nsswitch.conf
335 # ---- set the name of the network interfaces if requested on the boot argv
336 if grep -q -E 'nameif=[0-9,!:a-fA-F]*' /proc/cmdline
338 good_msg "Renaming the network interfaces (option 'nameif' was used)"
339 ethlist="$(/sbin/ifconfig -a | grep 'HWaddr' | grep '^eth[0-9]*' | awk '{print $1}')"
340 maclist="$(/sbin/ifconfig -a | grep 'HWaddr' | grep '^eth[0-9]*' | awk '{print $5}')"
342 # ---- get the option from the boot command line # eg: "nameif=eth0!00:11:22:33:44:55,eth1!00:22:33:44:55:aa"
344 for x in $(cat /proc/cmdline)
346 if echo "${x}" | grep -q -E 'nameif=[0-9,!:a-fA-F]*'
348 NAMEIFOPT="$(echo ${x} | cut -d= -f2 | sed -e 's!,! !g')"
352 # ---- rename all the network interfaces so that each name is free for another interface
354 for curmac in ${maclist}
356 cmd="busybox nameif iftmp${pos} ${curmac}"
358 echo "netconfig1: ${cmd} --> $?"
362 # ---- rename the interfaces with the name requested on the boot command
363 for val in ${NAMEIFOPT}
367 name="$(echo ${opt} | cut -d! -f1)"
368 mac="$(echo ${opt} | cut -d! -f2)"
370 cmd="busybox nameif $name $mac"
372 echo "netconfig1: ${cmd} --> $?"
377 # ---- attribute the remaining names to the remaining network interfaces
378 maclist="$(/sbin/ifconfig -a | grep 'HWaddr' | grep '^iftmp[0-9]*' | awk '{print $5}')"
379 for curmac in ${maclist}
383 while [ "${pos}" -lt 99 ] && [ "$ifdone" = '0' ]
386 if ! /sbin/ifconfig -a | grep 'HWaddr' | grep -q "^${curif}"
388 cmd="busybox nameif $curif $curmac"
390 echo "netconfig1: ${cmd} --> $?"
399 if [ "${NETCONFIG}" = '1' ] # show interfaces detected with the new name
401 ethlist="$(/sbin/ifconfig -a | grep 'HWaddr' | grep '^eth[0-9]*' | awk '{print $1}')"
403 if [ -z "${ethlist}" ]
405 echo "No ethernet interfaces found on your system, PXE boot won't work."
408 echo "Here are the ethernet interfaces found on your system:"
410 # ---- get the option from the boot command line # eg: "nameif=eth0!00:11:22:33:44:55,eth1!00:22:33:44:55:aa"
411 for cureth in ${ethlist}
413 #cureth="${ethlist[curpos]}"
414 curmac="$(/sbin/ifconfig ${cureth} | grep 'HWaddr' | grep '^eth[0-9]*' | awk '{print $5}')"
415 echo "* ${cureth}: ${curmac}"
416 ifconfig ${cureth} up
421 # ---- configure the ethernet interfaces if requested by 'ethx=ip' ----
422 if [ -n "${SETETHX}" ]
424 echo "netconfig1: found option ethx=${SETETHX}"
425 ethlist="$(/sbin/ifconfig -a | grep 'eth' | awk '{print $1}' | busybox xargs)" # (eg: eth0 eth1 eth2)
426 for cureth in ${ethlist}
428 netconfig_setip ${SETETHX} ${cureth}
432 # ---- configure individual ethernet interfaces ----
433 if cat /proc/cmdline | grep -q -E 'eth[0-9]{1,2}=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
435 # parse the command line for individual ethernet interfaces settings
436 for x in $(cat /proc/cmdline)
438 if echo "${x}" | grep -q -E 'eth[0-9]{1,2}=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
440 iface=$(echo ${x} | cut -d= -f1)
441 ipaddr=$(echo ${x} | cut -d= -f2)
442 echo "netconfig1: found option ${x}"
443 netconfig_setip ${ipaddr} ${iface}
448 # ---- configure the network via dhcp ----
449 if [ "${DODHCP}" = '1' ]
451 ethlist="$(/sbin/ifconfig -a | grep 'eth' | awk '{print $1}' | busybox xargs)" # (eg: eth0 eth1 eth2)
454 while [ "${dhcpstate}" != 'ok' ] # retry until we get a dhcp address on at least one interface
456 for cureth in ${ethlist}
458 # Try to find whether or not the link is connected
459 mac=$(ifconfig ${cureth} | grep HWaddr | awk '{print $5}')
460 if [ -f /sbin/mii-tool ] && /sbin/mii-tool ${cureth} 2>/dev/null | grep -qF 'link ok'
463 elif [ -f /sbin/mii-tool ] && /sbin/mii-tool ${cureth} 2>/dev/null | grep -qF 'no link'
466 else # if not sure, set linkstate='unknown'
469 echo "--- ${cureth}: link=${linkstate}, mac=${mac}"
471 # If the link is up, then try (even if another interface already has a dhcp address)
472 if [ "${linkstate}" != 'no-link' ]
474 good_msg "Attempting to get a DHCP address on ${cureth}..."
475 [ -n "${DHCPHOSTNAME}" ] && hostnameopt="-H ${DHCPHOSTNAME}"
476 cmd="busybox udhcpc -n -i ${cureth} ${hostnameopt}"
478 echo "${cmd} --> ${res}"
479 [ "${res}" = '0' ] && dhcpstate='ok'
483 if [ "${dhcpstate}" != 'ok' ]
485 echo "Cannot get a DHCP address. Check the cables on the ethernet interfaces."
491 # ---- configure the gateway if requested on cmdline ----
494 while route del default gw 0.0.0.0 2>&-
496 echo "netconfig1: removing old default route"
498 echo "netconfig1: set new default route to ${SETGW}"
499 route add default gw ${SETGW}
502 # ---- configure the nameserver if requested on cmdline ----
503 if [ -n "${SETDNS}" ]
505 rm -f /etc/resolv.conf 2>/dev/null
506 echo "netconfig1: set nameserver to ${SETDNS}"
507 echo "nameserver ${SETDNS}" > /etc/resolv.conf
511 sysresccd_setup_volumes()
513 # Setup dmraid for fake raid devices
514 if [ -x "/sbin/dmraid-activate" ] && ! grep -q 'nodmraid' /proc/cmdline
516 good_msg "Activating dmraid (fake hardware raid)..."
517 if devices=$(dmraid -r -c)
526 # Setup mdadm for linux software raid
527 if [ -x "/sbin/mdadm" ] && ! grep -q 'nomdadm' /proc/cmdline
529 good_msg "Loading MD modules for software raid..."
530 for mod in linear multipath raid0 raid1 raid456 raid5 raid6 raid10
534 good_msg "Starting mdadm (linux software raid)"
535 /sbin/mdadm -Es > /etc/mdadm.conf
539 # Setup the Logical Volume Manager
540 if [ -x "/sbin/lvm" ] && ! grep 'nolvm' /proc/cmdline
542 good_msg 'Setting up the Logical Volume Manager'
543 /sbin/lvm vgscan --ignorelockingfailure --mknodes 2>/dev/null
544 /sbin/lvm vgchange -ay --ignorelockingfailure 2>/dev/null
548 # ============================================================================================================
552 # check the kernel is able to execute /sbin/init
553 good_msg "Checking ${INITPROG} can be executed by the current kernel..."
554 inittype="$(readelf -h ${NEWROOT}${INITPROG} | grep Class | awk '{print $2}')"
555 archtype="$(uname -m)"
556 echo " ${INITPROG} on the root filesystem is an ${inittype} binary"
557 echo " The current running kernel architecture is ${archtype}"
558 if [ "${inittype}" = 'ELF64' ] && [ "${archtype}" != 'x86_64' ]
560 sysresccd_panic "You must boot with a 64bit kernel such as rescue64 to run ${INITPROG}"
563 # move /dev to the new root filesystem
564 mount -n -o move /dev ${NEWROOT}/dev
566 ln -s ${NEWROOT}/dev /dev
568 if [ ! -x ${NEWROOT}${INITPROG} ]
570 sysresccd_panic "${INITPROG} not found on root filesystem"
576 good_msg "Executing ${INITPROG} from the root filesystem..."
577 exec run-init ${NEWROOT} ${INITPROG} <${NEWROOT}/dev/console >${NEWROOT}/dev/console
579 # ------------------------------- minishell -------------------------------
580 sysresccd_panic "Failed to run run-init ${NEWROOT} ${INITPROG}"
583 # ============================================================================================================
584 # ============================================================================================================
586 sysresccd_stage1_http()
588 if ! mount -t tmpfs -o ${CACHESIZE} tmpfs ${BOOTPATH}
590 sysresccd_panic "Cannot create tmpfs on ${BOOTPATH}"
593 if ! echo "${HTTPBOOT}" | grep -q '^http://'
595 sysresccd_panic "You requested an http boot, the address is not a valid http:// url."
598 good_msg "Downloading ${LOOPDAT} from ${HTTPBOOT}"
599 BOOTMD5=$(echo ${HTTPBOOT} | sed -e "s/${LOOPDAT}/${LOOPMD5}/g") # URL of the md5 file
600 /bin/busybox wget ${BOOTMD5} -O ${BOOTPATH}/${LOOPMD5}
602 /bin/busybox wget ${HTTPBOOT} -O ${BOOTPATH}/${LOOPDAT}
605 if [ ${res1} -ne 0 ] || [ ${res2} -ne 0 ]
607 sysresccd_panic "Cannot download the files: wget failed. May be due to lack of memory"
610 if [ ! -f "${BOOTPATH}/${LOOPDAT}" ]
612 sysresccd_panic "Cannot download the \"${LOOPDAT}\" boot file."
615 md5now=$(/bin/busybox md5sum ${BOOTPATH}/${LOOPDAT} | cut -d ' ' -f1)
616 md5orig=$(cat ${BOOTPATH}/${LOOPMD5} | cut -d ' ' -f1)
617 if [ "$md5now" = "$md5orig" ]
619 good_msg "Downloaded boot file to \"${BOOTPATH}/${LOOPDAT}\""
621 sysresccd_panic "The root filesystem image is invalid: md5sum failed"
625 sysresccd_stage1_tftp()
627 if ! mount -t tmpfs -o ${CACHESIZE} tmpfs ${BOOTPATH}
629 sysresccd_panic "Cannot create tmpfs on ${BOOTPATH}"
632 if ! echo "${TFTPBOOT}" | grep -q '^tftp://'
634 sysresccd_panic "You requested an tftp boot, the address is not a valid tftp:// url."
637 good_msg "Downloading ${LOOPDAT} from ${TFTPBOOT}"
638 url="$(echo ${TFTPBOOT} | sed 's!tftp://!!g')" # remote the 'tftp://' prefix
641 BOOTMD5=$(echo ${tftpurl} | sed -e "s/${LOOPDAT}/${LOOPMD5}/g") # URL of the md5 file
642 cmd1="/bin/busybox tftp -g -r ${BOOTMD5} -l ${BOOTPATH}/${LOOPMD5} ${tftpip}"
645 cmd2="/bin/busybox tftp -g -r ${tftpurl} -l ${BOOTPATH}/${LOOPDAT} ${tftpip}"
649 if [ "$res1" != '0' ] || [ "$res2" != '0' ]
651 sysresccd_panic "Cannot download the files, wget failed. May be due to lack of memory"
654 if [ ! -f "${BOOTPATH}/${LOOPDAT}" ]
656 sysresccd_panic "Cannot download the \"${LOOPDAT}\" boot file."
659 md5now=$(/bin/busybox md5sum ${BOOTPATH}/${LOOPDAT} | cut -d ' ' -f1)
660 md5orig=$(cat ${BOOTPATH}/${LOOPMD5} | cut -d ' ' -f1)
661 if [ "$md5now" = "$md5orig" ]
663 good_msg "Downloaded boot file to \"${BOOTPATH}/${LOOPDAT}\""
665 sysresccd_panic "The root filesystem image is invalid: md5sum failed"
669 sysresccd_stage1_nfs()
671 nfsurl=$(echo ${NFSBOOT} | sed -e 's!nfs://!!g')
673 good_msg "Mouting the NFS filesystem from ${NFSBOOT}"
674 cmd="mount -t nfs -o intr,nolock ${nfsurl} ${BOOTPATH}"
677 sysresccd_panic "Cannot mount NFS: ${cmd}"
679 good_msg "Successfully mounted the NFS filesystem"
681 if [ ! -f "${BOOTPATH}/${SUBDIR}/${LOOPDAT}" ]
683 sysresccd_panic "Cannot find the \"${SUBDIR}/${LOOPDAT}\" boot file."
686 md5now=$(/bin/busybox md5sum ${BOOTPATH}/${SUBDIR}/${LOOPDAT} | cut -d ' ' -f1)
687 md5orig=$(cat ${BOOTPATH}/${SUBDIR}/${LOOPMD5} | cut -d ' ' -f1)
688 if [ "$md5now" = "$md5orig" ]
690 good_msg "Successfully checked md5 sum of ${BOOTPATH}/${LOOPDAT}"
692 sysresccd_panic "md5sum checksum is invalid on the root filesystem image"
696 # find the device that contains a file with that path: ${SUBDIR}/${LOOPDAT}
697 sysresccd_find_file() # $1=devtype, $2=filepath $3=mountdir, $4=mode
699 devtype="$1" # on which devices should we search that file
700 filepath="$2" # path of the file we are looking for (eg: "/sysrcd.dat")
701 mountdir="$3" # where to mount the device if we find it
702 mountmode="$4" # mount mode: either 'ro' or 'rw'
706 searchdevices=$(sysresccd_expand_alldevices ${BLKDEVICES})
708 rmdev) # removable devices only
709 searchdevices=$(sysresccd_expand_removable ${BLKDEVICES})
711 UUID\=*) # find file on filesystem having the speficed UUID
712 uuid=`parse_opt "${devtype}"`
713 target="$(/bin/readlink -f /dev/disk/by-uuid/${uuid})"
714 if [ -b "${target}" ]
716 searchdevices="${target}"
717 elif [ -b "/dev/disk/by-uuid/${uuid}" ]
719 searchdevices="/dev/disk/by-uuid/${uuid}"
722 LABEL\=*) # find file on filesystem having the speficed LABEL
723 label=`parse_opt "${devtype}"`
724 target="$(/bin/readlink -f /dev/disk/by-label/${label})"
725 if [ -b "${target}" ]
727 searchdevices="${target}"
728 elif [ -b "/dev/disk/by-label/${uuid}" ]
730 searchdevices="/dev/disk/by-label/${uuid}"
733 *) # specific device name (eg: "/dev/sda1")
734 searchdevices="${devtype}"
738 SEARCHDEVICE='' # result returned
740 for curdev in ${searchdevices}
742 if [ -b "${curdev}" ] # Check for a block device to mount
744 # check the 'skipmount=/dev/xxx' option (use it with a failing hard drive)
745 # compare with a space at the end so that "/dev/sda1" and "/dev/sda11" don't match
746 if echo "$(cat /proc/cmdline) " | grep -F -q "skipmount=${curdev} "
748 good_msg "Skipping mount on device: ${curdev}"
750 good_msg "Attempting to mount device: ${curdev}"
752 for curfs in vfat msdos iso9660 ntfs auto
756 mntopt='-o mode=0644'
759 mntopt='-o fmask=0133'
766 if mount -r -t ${curfs} ${curdev} ${mountdir} ${mntopt} >/dev/null 2>&1
768 if [ -e ${mountdir}/${filepath} ]
770 SEARCHDEVICE="${curdev}"
771 good_msg "File ${filepath} found on device ${curdev}"
772 if [ "${mountmode}" = 'rw' ] && ! mount -o remount,rw,noatime ${mountdir}
774 sysresccd_panic "Cannot remount ${curdev} in read-write mode"
778 umount ${mountdir} >/dev/null 2>&1
788 # find the device which contains sysrcd.dat and mount it on ${BOOTPATH}
789 sysresccd_stage1_normal()
791 good_msg "Searching for ${SUBDIR}/${LOOPDAT} on devices..."
793 for attempts in 1 2 3 4 5
795 [ ${attempts} -gt 1 ] && sleep 3 && bad_msg "Cannot find device with ${SUBDIR}/${LOOPDAT}. Retrying..."
796 if sysresccd_find_file 'auto' ${SUBDIR}/${LOOPDAT} ${BOOTPATH} 'ro'
798 if [ "${DOCHECK}" = '1' ] # don't run checksum by default on slow medias (cdrom, usb, ...)
800 if [ ! -f "${BOOTPATH}/${SUBDIR}/${LOOPMD5}" ]
802 bad_msg "Cannot find md5 checksum file: ${LOOPMD5}"
804 md5now=$(/bin/busybox md5sum ${BOOTPATH}/${SUBDIR}/${LOOPDAT} | cut -d ' ' -f1)
805 md5orig=$(cat ${BOOTPATH}/${SUBDIR}/${LOOPMD5} | cut -d ' ' -f1)
806 if [ "$md5now" = "$md5orig" ]
808 good_msg "md5 checksum of ${LOOPDAT} successfully checked"
810 sysresccd_panic "md5sum checksum is invalid on the root filesystem image"
819 if [ -z "${filefound}" ]
821 sysresccd_panic "Cannot find ${SUBDIR}/${LOOPDAT} on devices"
824 if [ "${DOCACHE}" = '1' ]
826 good_msg "Creating tmpfs for caching in ${CACHEDIR}"
827 if ! mount -t tmpfs -o ${CACHESIZE} tmpfs ${CACHEDIR}
829 sysresccd_panic "Cannot mount tmpfs filesystem on ${CACHEDIR} for caching"
832 # --------------- Get loopfile size
833 squashfspath="${BOOTPATH}/${SUBDIR}/${LOOPDAT}"
834 squashfssize=$(ls -l "$squashfspath" | sed -e ":a;s/ / /g;ta" | cut -f 5 -d ' ') # size in bytes
835 squashfssizekb=$(( $squashfssize / 1024 )) # size in kilo-bytes
837 # --------------- Cache autorun files
838 autoruns="$(ls -d ${BOOTPATH}/${SUBDIR}/autorun* 2>/dev/null)"
839 [ "$autoruns" != "" ] && cp $autoruns ${CACHEDIR}/
841 # --------------- Cache main loop file
842 cp -a ${BOOTPATH}/${SUBDIR}/version ${CACHEDIR}/ 2>/dev/null
843 cp -a ${BOOTPATH}/${SUBDIR}/${LOOPMD5} ${CACHEDIR}/${LOOPMD5} 2>/dev/null
844 good_msg "Copying ${LOOPDAT} file for caching (size: $squashfssizekb KB)..."
845 cp -a ${BOOTPATH}/${SUBDIR}/${LOOPDAT} ${CACHEDIR}/${LOOPDAT} 2>/dev/null
847 # --------------- Check main loop file
848 expectedsize=$(/bin/busybox stat -c%s "${BOOTPATH}/${SUBDIR}/${LOOPDAT}")
849 copiedsize=$(/bin/busybox stat -c%s "${CACHEDIR}/${LOOPDAT}")
851 if [ "${copiedsize}" != "${expectedsize}" ] # Was the copy completed successfully ?
852 then # docache failed
853 bad_msg "Caching failed. Likely due to lack of memory"
854 rm -f "${CACHEDIR}/${LOOPDAT}"
855 umount ${CACHEDIR} 2>/dev/null
857 else # docache successful
858 good_msg "File ${LOOPDAT} successfully cached"
861 # cache other files if possible
862 if [ -z "${LOWMEM}" ] && [ -d ${BOOTPATH}/${SUBDIR}/isolinux ] && [ -d ${BOOTPATH}/${SUBDIR}/bootdisk ] && [ -d ${BOOTPATH}/${SUBDIR}/ntpasswd ]
864 good_msg "Copying isolinux + bootdisk + ntpasswd for caching..."
865 if ! cp -a ${BOOTPATH}/${SUBDIR}/isolinux ${BOOTPATH}/${SUBDIR}/bootdisk ${BOOTPATH}/${SUBDIR}/ntpasswd ${CACHEDIR}/ #2>/dev/null
867 rm -rf ${CACHEDIR}/{isolinux,bootdisk,ntpasswd}
868 bad_msg "Cannot cache isolinux and bootdisk. Likely due to lack of memory"
872 # unmount the media if possible
873 if umount ${BOOTPATH}
875 good_msg "The original media has been unmounted"
876 cmd="mount -n --move ${CACHEDIR} ${BOOTPATH}"
879 bad_msg "${cmd} --> ${res}" && sleep 3
882 bad_msg "Cannot unmount the original media"
885 # unmount isostore if necessary
886 if cat /proc/mounts | awk '{print $2}' | grep -q "^${ISOSTORE}$"
888 if losetup -d /dev/loop0
890 umount ${ISOSTORE} && good_msg "Unmounted ${ISOSTORE}" || bad_msg "Cannot unmount ${ISOSTORE}"
897 sysresccd_stage2_nbd()
899 nbdurl=$(echo ${NBDBOOT} | sed -e 's!nbd://!!g')
900 NBD_SERVER=$(echo "${nbdurl}" | sed 's/:.*//')
901 NBD_PORT=$(echo "${nbdurl}" | sed 's/.*://')
904 NBD_DEVICE="/dev/nbd0"
905 NBD_PROG="/sbin/nbd-client"
907 if [ ! -x "${NBD_PROG}" ]
909 sysresccd_panic "Error: program ${NBD_PROG} not found"
914 sysresccd_panic "Error: cannot load nbd kernel module"
917 good_msg "Setting up the NBD boot device..."
918 if ! ${NBD_PROG} "${NBD_SERVER}" "${NBD_PORT}" "${NBD_DEVICE}" -persist
920 sysresccd_panic "Error: nbd-client failed to connect to ${NBD_SERVER}:${NBD_PORT}"
922 good_msg "nbd-client successfully connected to ${NBD_SERVER}:${NBD_PORT}"
925 cmd="mount -t squashfs -o ro ${NBD_DEVICE} ${SQUASHFSMNT}"
928 sysresccd_panic "ERROR: Cannot mount ${NBD_DEVICE}. ${cmd}"
930 good_msg "successfully mounted ${NBD_DEVICE} on ${SQUASHFSMNT}"
934 sysresccd_stage2_normal() # mount ${BOOTPATH}/sysrcd.dat on ${SQUASHFSMNT}
936 good_msg "Mounting the squashfs root filesystem on ${SQUASHFSMNT}"
939 squashfsimg="${BOOTPATH}/${SUBDIR}/${LOOPDAT}"
940 for fs in '-t squashfs' ''
942 if [ "$mountok" != "ok" ]
944 mount ${fs} ${squashfsopt} -o ro ${squashfsimg} ${SQUASHFSMNT} 2>/dev/null && mountok='ok'
948 if [ "$mountok" != "ok" ]
950 sysresccd_panic "ERROR: Cannot mount ${LOOPDAT}. Kernel version [$(uname -a)]"
954 sysresccd_stage3_normal() # "backstore" + "aufs" + "mount --move"
956 # 1. search for a backstore file ("sysrcd.bs" by default)
958 if [ "${BACKSTORE_CMD}" != 'off' ]
960 BACKSTORE_DEVTYPE='rmdev' # by default search backstores only on removable devices
961 for curopt in $(echo ${BACKSTORE_CMD} | sed -e 's!,! !g')
965 BACKSTORE_DEVTYPE='auto' # search for backstores on all types of devices
968 BACKSTORE_DAT=${curopt} # search for backstores on that particular device
973 good_msg "Searching for ${SUBDIR}/${BACKSTORE_DAT} on devices..."
974 if sysresccd_find_file ${BACKSTORE_DEVTYPE} ${SUBDIR}/${BACKSTORE_DAT} ${BACKSTORE_MNT} 'rw'
976 good_msg "Backing store ${SUBDIR}/${BACKSTORE_DAT} found on ${SEARCHDEVICE}"
977 if ! mount ${BACKSTORE_MNT}/${SUBDIR}/${BACKSTORE_DAT} ${BACKSTORE_MEM}
979 sysresccd_panic "Cannot mount the loopback backstore file ${SUBDIR}/${BACKSTORE_DAT}"
985 # 2. store modifications in a tmpfs filesystem if there is no backstore
986 if [ -z "${BACKSTORE_FOUND}" ] && ! mount -t tmpfs tmpfs ${BACKSTORE_MEM}
988 sysresccd_panic "Fatal error: cannot mount tmpfs on ${BACKSTORE_MEM}"
991 # 3. create the aufs filesystem
992 if ! grep -q aufs /proc/filesystems
994 sysresccd_panic "Fatal error: aufs filesystem not supported by the kernel."
996 if mount -t aufs none ${NEWROOT} -o dirs=${BACKSTORE_MEM}=rw:${SQUASHFSMNT}=ro -o noatime
998 good_msg "The aufs filesystem has been created"
1000 sysresccd_panic "Fatal error: cannot mount the aufs filesystem."
1003 # 4. copy cached autorun scripts
1004 autoruns="$(ls -d ${CACHEDIR}/autorun* 2>/dev/null)"
1005 [ "$autoruns" != "" ] && cp $autoruns ${NEWROOT}/var/autorun/cdrom
1007 # 5. move filesystems mount points to the newroot
1008 for mntdir in ${BOOTPATH} ${SQUASHFSMNT} ${BACKSTORE_MNT} ${BACKSTORE_MEM} ${ISOSTORE}
1010 targetdir="${NEWROOT}/livemnt/${mntdir}"
1011 if cat /proc/mounts | awk '{print $2}' | grep -q "^${mntdir}$"
1013 mkdir -p ${targetdir} 2>/dev/null
1014 cmd="mount -n --move ${mntdir} ${targetdir}"
1017 sysresccd_panic "${cmd} failed"
1023 for curdir in /mnt/custom /mnt/gentoo /mnt/windows /mnt/floppy /mnt/backup \
1024 /var/run/iptraf /var/log/iptraf /var/spool/cron /var/run/samba \
1025 /var/log/samba /var/cache/samba /var/log/clamav /var/run/clamav
1027 mkdir -p "${NEWROOT}${curdir}"
1030 if [ -e /etc/sysconfig/keyboard ]
1032 mkdir -p ${NEWROOT}/etc/sysconfig/
1033 cp /etc/sysconfig/keyboard ${NEWROOT}/etc/sysconfig/keyboard
1036 # if option "lowmem" was enabled then do not start these initscripts
1037 if [ "${LOWMEM}" = '1' ]
1039 for initscr in sshd nfs portmap
1041 rm -f "${NEWROOT}/etc/runlevels/default/${initscr}"
1046 sysresccd_stage3_rootsys() # mount the root partition on ${SQUASHFSMNT}
1048 good_msg "Searching a root filesystem having ${INITPROG}"
1051 for attempts in 1 2 3 4 5
1053 [ ${attempts} -gt 1 ] && sleep 3 && bad_msg "Cannot find device with ${INITPROG}. Retrying..."
1054 if sysresccd_find_file ${ROOTOPT} ${INITPROG} ${NEWROOT} 'rw'
1061 if [ -z "${filefound}" ]
1063 sysresccd_panic "Cannot find a valid root filesystem (partition having ${INITPROG})"
1066 #NEWKERMODS="${NEWROOT}/lib/modules/$(uname -r)"
1067 #mkdir -p ${NEWKERMODS}
1068 #mount -t tmpfs tmpfs ${NEWKERMODS}
1069 #cp -a /lib/modules/$(uname -r)/* ${NEWKERMODS}/
1072 sysresccd_stage0_isoloop() # losetup the iso image on /dev/loop0
1074 good_msg "Searching for ${SUBDIR}/${ISOLOOP} on devices..."
1076 for attempts in 1 2 3 4 5
1078 [ ${attempts} -gt 1 ] && sleep 3 && bad_msg "Cannot find device with ${SUBDIR}/${ISOLOOP}. Retrying..."
1079 if sysresccd_find_file 'auto' ${SUBDIR}/${ISOLOOP} ${ISOSTORE} 'ro'
1086 if [ -z "${filefound}" ]
1088 sysresccd_panic "Cannot find device with ${SUBDIR}/${ISOLOOP}"
1091 if losetup /dev/loop0 ${ISOSTORE}/${SUBDIR}/${ISOLOOP}
1093 good_msg "Loopback device configured with ${ISOSTORE}/${SUBDIR}/${ISOLOOP}"
1095 bad_msg "Cannot configure /dev/loop0 with ${ISOSTORE}/${SUBDIR}/${ISOLOOP}"
1099 # =============================================================================
1101 sysresccd_stage0() # special preparations for isoroot
1105 sysresccd_stage0_isoloop
1114 sysresccd_stage1() # find sysrcd.dat and put it in ${BOOTPATH}
1124 sysresccd_stage1_http
1128 sysresccd_stage1_tftp
1132 sysresccd_stage1_nfs
1136 sysresccd_stage1_normal
1142 sysresccd_stage2() # mount ${BOOTPATH}/sysrcd.dat on ${SQUASHFSMNT}
1149 sysresccd_stage2_nbd
1153 sysresccd_stage2_normal
1159 sysresccd_stage3() # ${NEWROOT}=aufs
1163 sysresccd_stage3_rootsys
1166 sysresccd_stage3_normal
1171 # =============================================================================
1173 sysresccd_parsecmdline()
1175 for x in $(cat /proc/cmdline)
1179 INITPROG=`parse_opt "${x}"`
1182 SETETHX=`parse_opt "${x}"`
1192 SETDNS=`parse_opt "${x}"`
1196 SETGW=`parse_opt "${x}"`
1200 SETGW=`parse_opt "${x}"`
1204 DHCPHOSTNAME=`parse_opt "${x}"`
1208 HTTPBOOT=`parse_opt "${x}"`
1213 TFTPBOOT=`parse_opt "${x}"`
1218 NFSBOOT=`parse_opt "${x}"`
1223 NBDBOOT=`parse_opt "${x}"`
1228 ROOTOPT=`parse_opt "${x}"`
1232 ISOLOOP=`parse_opt "${x}"`
1239 SUBDIR=`parse_opt "${x}"`
1242 SPEAKUP=`parse_opt "${x}"`
1245 BACKSTORE_CMD=`parse_opt "${x}"`
1248 SETKMAP=`parse_opt "${x}"`
1251 SCANDELAY=`parse_opt "${x}"`
1257 MODLOAD=`parse_opt "${x}"`
1258 MODLOAD="`echo ${MODLOAD} | sed -e \"s/,/ /g\"`"
1264 BLACKLIST=`parse_opt "${x}"`
1265 BLACKLIST="`echo ${BLACKLIST} | sed -e \"s/,/ /g\"`"
1268 CONSOLE=`parse_opt "${x}"`
1269 exec >${CONSOLE} <${CONSOLE} 2>&1
1280 httpboot\=*) # for compatibility only
1281 HTTPBOOT=`parse_opt "${x}"`
1285 tftpboot\=*) # for compatibility only
1286 TFTPBOOT=`parse_opt "${x}"`
1290 boothttp\=*) # for compatibility only
1291 HTTPBOOT=`parse_opt "${x}"`
1295 boottftp\=*) # for compatibility only
1296 TFTPBOOT=`parse_opt "${x}"`
1300 nfsboot\=*) # for compatibility only
1301 ARG=`parse_opt "${x}"`
1302 NFSBOOT="nfs://${ARG}"
1306 nbdboot\=*) # for compatibility only
1307 ARG=`parse_opt "${x}"`
1308 NBDBOOT="nbd://${ARG}"
1316 # =============================================================================
1320 export PATH=/bin:/usr/bin:/sbin:/usr/sbin
1322 # only run as an init program
1325 echo '/linuxrc has to be run as the init process as the one'
1326 echo 'with a PID of 1. Try adding init="/linuxrc" to the'
1327 echo 'kernel command line or running "exec /linuxrc".'
1331 # create system directories
1332 [ -d /dev ] || mkdir -m 0755 /dev
1333 [ -d /root ] || mkdir -m 0700 /root
1334 [ -d /sys ] || mkdir /sys
1335 [ -d /proc ] || mkdir /proc
1336 [ -d /tmp ] || mkdir /tmp
1337 [ -d /selinux ] || mkdir /selinux
1338 [ -d /var/lock ] || mkdir -p /var/lock
1339 [ -d /usr/bin ] || mkdir -p /usr/bin
1340 [ -d /usr/sbin ] || mkdir -p /usr/sbin
1341 [ -d ${SQUASHFSMNT} ] || mkdir -p ${SQUASHFSMNT}
1342 [ -d ${BOOTPATH} ] || mkdir -p ${BOOTPATH}
1343 [ -d ${NEWROOT} ] || mkdir -p ${NEWROOT}
1344 [ -d ${BACKSTORE_MNT} ] || mkdir -p ${BACKSTORE_MNT}
1345 [ -d ${BACKSTORE_MEM} ] || mkdir -p ${BACKSTORE_MEM}
1346 [ -d ${ISOSTORE} ] || mkdir -p ${ISOSTORE}
1347 [ -d ${CACHEDIR} ] || mkdir -p ${CACHEDIR}
1349 # mount virtual filesystems
1350 /bin/busybox mount -t sysfs -o nodev,noexec,nosuid none /sys
1351 /bin/busybox mount -t proc -o nodev,noexec,nosuid none /proc
1354 /bin/busybox --install -s
1357 # =============================================================================
1387 SQUASHFSMNT='/squashfs'
1388 ISOSTORE='/isostore'
1390 BACKSTORE_MNT='/backstore'
1391 BACKSTORE_MEM='/memory'
1392 BACKSTORE_DAT='sysrcd.bs'
1393 LOOPDAT='sysrcd.dat'
1394 LOOPMD5='sysrcd.md5'
1395 INITPROG='/sbin/init'
1396 CONSOLE='/dev/console'
1398 CACHESIZE='size=512m'
1401 BLKDEVICES="/dev/cdroms/* /dev/ide/cd/* /dev/sr*"
1402 # USB Keychain/Storage
1403 BLKDEVICES="$BLKDEVICES /dev/sd*"
1405 BLKDEVICES="$BLKDEVICES /dev/hd*"
1406 # Loopback devices (used for isoloop=xxx)
1407 BLKDEVICES="$BLKDEVICES /dev/loop* /dev/loop/*"
1408 # USB using the USB Block Driver
1409 BLKDEVICES="$BLKDEVICES /dev/ubd* /dev/ubd/*"
1411 BLKDEVICES="$BLKDEVICES /dev/iseries/vcd*"
1413 BLKDEVICES="$BLKDEVICES /dev/cciss* /dev/cciss/*"
1415 BLKDEVICES="$BLKDEVICES /dev/dm* /dev/mapper/*"
1417 # =============================================================================
1420 sysresccd_parsecmdline
1422 sysresccd_udev_start
1424 sysresccd_setup_keymap
1425 sysresccd_setup_volumes