Replace leftover x86 with ${ARCH} in recreate-iso.sh
[systemrescuecd.git] / mainfiles / linuxrc
1 #!/bin/sh
2 # Copyright 2003-2006 Gentoo Foundation
3 # Copyright 2006-2010 Francois Dupoux
4 # Distributed under the terms of the GNU General Public License v2
5
6 good_msg()
7 {
8         msg_string=$1
9         msg_string="${msg_string:-...}"
10         [ "$2" != 1 ] && echo -e "${GOOD}>>${NORMAL} ${msg_string} ${NORMAL}"
11 }
12
13 bad_msg()
14 {
15         msg_string=$1
16         msg_string="${msg_string:-...}"
17         [ "$2" != 1 ] && echo -e "${BAD}!!${NORMAL} ${msg_string} ${NORMAL}"
18 }
19
20 parse_opt()
21 {
22         case "$1" in
23                 *\=*)
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}-
28                 ;;
29         esac
30 }
31
32 sysresccd_expand_alldevices()
33 {
34         for curdev in $*
35         do
36                 echo ${curdev}
37         done
38 }
39
40 sysresccd_expand_removable()
41 {
42         # Look for the value of 1 in the file /sys/block/sd*/removable
43         for curdev in $*
44         do
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}
48         done
49 }
50
51 sysresccd_runshell()
52 {
53         if [ -n "$1" ] && [ -x "$1" ]
54         then
55                 exec "$1"
56         else
57                 exec /bin/sh
58         fi
59         exit 1
60 }
61
62 sysresccd_panic()
63 {
64         bad_msg "$@"
65         bad_msg "Running a mini shell (cannot complete the boot process)"
66         sleep 2
67         sysresccd_runshell
68 }
69
70 sysresccd_setup_keymap()
71 {
72         if [ -z "$SETKMAP" ]
73         then
74                 if [ ! -e /dev/vc/0 -a ! -e /dev/tty0 ]
75                 then
76                         DEVBIND=1
77                         mount -o bind ${NEWROOT}/dev /dev
78                 fi
79                 [ ! -e /dev/tty0 ] && ln -s /dev/tty1 /dev/tty0
80
81                 sysresccd_chooseKeymap
82
83                 [ "${DEVBIND}" -eq '1' ] && umount /dev
84         else # "setkmap=xx" option was used
85                 sysresccd_useKeymap $SETKMAP
86         fi
87 }
88
89 sysresccd_useKeymap()
90 {
91         keymap=$1
92
93         if [ -e /lib/keymaps/${keymap}.map ]
94         then
95                 good_msg "Loading the ''${keymap}'' keymap"
96                 loadkmap < /lib/keymaps/${keymap}.map
97                 xkeymap=${keymap}
98                 echo ${keymap} | grep -e "[0-9]+" >/dev/null 2>&1
99                 if [ "$?" -eq '0'  ]
100                 then
101                         xkeymap=`tail -n 7 /lib/keymaps/keymapList | grep ${keymap} | sed -r "s/.*\s+${keymap}\s+([a-z-]+).*/\1/g" | grep -v 1`
102                 fi
103                 mkdir -p /etc/sysconfig
104                 echo "XKEYBOARD=${xkeymap}" > /etc/sysconfig/keyboard
105         elif [ "$keymap" = '' ]
106         then
107                 echo
108                 good_msg "Keeping default keymap"
109         else
110                 bad_msg "Sorry, but keymap ''${keymap}'' is invalid!"
111                 sysresccd_chooseKeymap
112         fi
113 }
114
115 sysresccd_chooseKeymap()
116 {
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
122 }
123
124 sysresccd_terminal()
125 {
126         # set terminal in utf8 mode
127         kbd_mode -u
128         #/bin/consolechars -f /lat0-sun16.psf
129         #dumpkeys | loadkeys --unicode
130 }
131
132 sysresccd_debug()
133 {
134         # Run debug shell if requested with "minishell" in cmdline
135         if [ "${MINISHELL}" = '1' ]
136         then
137                 good_msg "Running a mini shell (as requested by the command line)"
138                 sysresccd_runshell ${MINISHELL}
139         fi
140 }
141
142 # ---- convert a short netmask (eg: '/24') to a long one ----
143 netmask_shorttolong() # eg: '24' ==> '255.255.255.0'
144 {
145         mask="$1"
146         if [ -n "${mask}" ]
147         then
148                 [ "${mask}" -gt '32' ] && mask='32'
149                 [ "${mask}" -lt '0' ] && mask='0'
150                 bit=0
151                 for i in 0 1 2 3
152                 do
153                         curbyte=0
154                         for j in 0 1 2 3 4 5 6 7
155                         do
156                                 curbit=0 ; [ "$bit" -lt "$mask" ] && curbit=1
157                                 curbyte=$((curbyte*2))
158                                 curbyte=$((curbyte+curbit))
159                                 bit=$((bit+1))
160                         done
161                         echo -n "$curbyte"
162                         [ "$i" -lt '3' ] && echo -n '.'
163                 done
164         fi
165 }
166
167 # configure an interface: eg: $1='192.168.1.1/24' $2='eth0'
168 netconfig_setip()
169 {
170         ethip=$1
171         cureth=$2
172         ipaddrbase=${ethip%%/*} # '192.168.1.1/24' --> '192.168.1.1'
173
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})$'
175         then
176                 ipaddrmask=${ethip#*/} # '192.168.1.1/24' --> '24'
177         else
178                 ipaddrmask=''
179         fi
180
181         if [ -n "${ipaddrmask}" ]
182         then
183                 iplongmask=$(netmask_shorttolong $ipaddrmask  2>/dev/null)
184                 maskopt="netmask ${iplongmask}"
185                 echo "netconfig1: netmask_shorttolong($ipaddrmask)=$iplongmask"
186         else
187                 iplongmask=''
188                 maskopt=''
189         fi
190
191         echo "netconfig1: configure ${cureth} to ${ethip}"
192         ipcmd_add="ifconfig ${cureth} ${ipaddrbase} ${maskopt}"
193         ${ipcmd_add} ; res=$?
194         echo "netconfig1: ${ipcmd_add} --> ${res}"
195 }
196
197 sysresccd_speakup()
198 {
199         if [ -n "${SPEAKUP}" ]
200         then
201                 OPTLIST="$(echo ${SPEAKUP} | sed -e 's!,! !g')"
202
203                 for curopt in ${OPTLIST}
204                 do
205                         for x in ${curopt}
206                         do
207                                 case "${x}" in
208                                         quiet\=*)
209                                                 SPEAKUP_QUIET=`parse_opt "${x}"`
210                                                 ;;
211                                         synth\=*)
212                                                 SPEAKUP_SYNTH=`parse_opt "${x}"`
213                                                 ;;
214                                         port\=*)
215                                                 SPEAKUP_PORT=`parse_opt "${x}"`
216                                                 SPEAKUP_OPTIONS="${SPEAKUP_OPTIONS} port=${SPEAKUP_PORT}"
217                                                 ;;
218                                         ser\=*)
219                                                 SPEAKUP_SER=`parse_opt "${x}"`
220                                                 SPEAKUP_OPTIONS="${SPEAKUP_OPTIONS} ser=${SPEAKUP_SER}"
221                                                 ;;
222                                 esac
223                         done
224                 done
225
226                 if [ -n "${SPEAKUP_QUIET}" ]
227                 then
228                         cmd="modprobe speakup quiet=${SPEAKUP_QUIET}"
229                         ${cmd}
230                 fi
231
232                 if [ -n "${SPEAKUP_SYNTH}" ]
233                 then
234                         cmd="modprobe speakup_${SPEAKUP_SYNTH} ${SPEAKUP_OPTIONS} start=1"
235                         ${cmd}
236                 fi
237         fi
238 }
239
240 sysresccd_udev_start()
241 {
242         good_msg "Loading modules..."
243
244         echo '0' > /proc/sys/kernel/printk
245
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
248         tmpfs_size="10M"
249         if [ -e /etc/udev/udev.conf ]; then
250                 . /etc/udev/udev.conf
251         fi
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
257
258         # Set modprobe env
259         export MODPROBE_OPTIONS="-qb"
260
261         # delete the useless modules
262         ls /lib/modules | grep -v $(uname -r) | busybox xargs rm -rf
263
264         # process module dependencies
265         depmod -a
266
267         # load custom modules
268         for modname in ${MODLOAD}
269         do
270                 modprobe ${modname}
271                 if [ $? -eq 0 ]
272                 then
273                         good_msg "modprobe ${modname} successful"
274                 else
275                         bad_msg "modprobe ${modname} failed (res=$?)"
276                 fi
277         done
278
279         # write blacklist to modprobe.d
280         for modname in ${BLACKLIST}
281         do
282                 echo "blacklist ${modname}" >> /etc/modprobe.d/initramfs
283                 good_msg "module ${modname} has been blacklisted"
284         done
285
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/
291         udevadm trigger
292         udevadm settle || true
293
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}
297
298         # show list of modules which have been loaded
299         modcount=0
300         modlist=''
301         while read modname details
302         do
303                 [ ${modcount} -ge 1 ] && modlist="${modlist}, "
304                 modlist="${modlist}${modname}"
305                 modcount=$((modcount+1))
306         done < /proc/modules
307         echo "${modlist}"
308 }
309
310 sysresccd_udev_stop()
311 {
312         # Stop udevd, we'll miss a few events while we run init, but we catch up
313         for proc in /proc/[0-9]*
314         do
315                 [ -x $proc/exe ] || continue
316                 [ "$(busybox readlink $proc/exe)" != /sbin/udevd ] || kill ${proc#/proc/}
317         done
318         echo '6' > /proc/sys/kernel/printk
319 }
320
321 sysresccd_netconfig()
322 {
323         good_msg "Performing the network configuration..."
324
325         # ---- force dhcp if booting via pxe and no static configuration specified
326         if [ "${NETCONFIG}" = '1' ] && [ -z "${SETETHX}" ]
327         then
328                 DODHCP='1'
329         fi
330
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
334
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
337         then
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}')"
341
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"
343                 NAMEIFOPT=''
344                 for x in $(cat /proc/cmdline)
345                 do
346                         if echo "${x}" | grep -q -E 'nameif=[0-9,!:a-fA-F]*'
347                         then
348                                 NAMEIFOPT="$(echo ${x} | cut -d= -f2 | sed -e 's!,! !g')"
349                         fi
350                 done
351
352                 # ---- rename all the network interfaces so that each name is free for another interface
353                 pos=0
354                 for curmac in ${maclist}
355                 do
356                         cmd="busybox nameif iftmp${pos} ${curmac}"
357                         ${cmd}
358                         echo "netconfig1: ${cmd} --> $?"
359                         pos=$((pos+1))
360                 done
361
362                 # ---- rename the interfaces with the name requested on the boot command
363                 for val in ${NAMEIFOPT}
364                 do
365                         for opt in ${val}
366                         do
367                                 name="$(echo ${opt} | cut -d! -f1)"
368                                 mac="$(echo ${opt} | cut -d! -f2)"
369
370                                 cmd="busybox nameif $name $mac"
371                                 ${cmd}
372                                 echo "netconfig1: ${cmd} --> $?"
373                                 sleep 1
374                         done
375                 done
376
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}
380                 do
381                         pos=0
382                         ifdone=0
383                         while [ "${pos}" -lt 99 ] && [ "$ifdone" = '0' ]
384                         do
385                                 curif="eth${pos}"
386                                 if ! /sbin/ifconfig -a | grep 'HWaddr' | grep -q "^${curif}"
387                                 then
388                                         cmd="busybox nameif $curif $curmac"
389                                         ${cmd}
390                                         echo "netconfig1: ${cmd} --> $?"
391                                         ifdone=1
392                                         sleep 1
393                                 fi
394                                 pos=$((pos+1))
395                         done
396                 done
397         fi
398
399         if [ "${NETCONFIG}" = '1' ] # show interfaces detected with the new name
400         then
401                 ethlist="$(/sbin/ifconfig -a | grep 'HWaddr' | grep '^eth[0-9]*' | awk '{print $1}')"
402
403                 if [ -z "${ethlist}" ]
404                 then
405                         echo "No ethernet interfaces found on your system, PXE boot won't work."
406                         sleep 2
407                 else
408                         echo "Here are the ethernet interfaces found on your system:"
409
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}
412                         do
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
417                         done
418                 fi
419         fi
420
421         # ---- configure the ethernet interfaces if requested by 'ethx=ip' ----
422         if [ -n "${SETETHX}" ]
423         then
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}
427                 do
428                         netconfig_setip ${SETETHX} ${cureth}
429                 done
430         fi
431
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}'
434         then
435                 # parse the command line for individual ethernet interfaces settings
436                 for x in $(cat /proc/cmdline)
437                 do
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}'
439                         then
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}
444                         fi
445                 done
446         fi
447
448         # ---- configure the network via dhcp ----
449         if [ "${DODHCP}" = '1' ]
450         then
451                 ethlist="$(/sbin/ifconfig -a | grep 'eth' | awk '{print $1}' | busybox xargs)" # (eg: eth0 eth1 eth2)
452
453                 dhcpstate=''
454                 while [ "${dhcpstate}" != 'ok' ] # retry until we get a dhcp address on at least one interface
455                 do
456                         for cureth in ${ethlist}
457                         do
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'
461                                 then
462                                         linkstate='link-ok'
463                                 elif [ -f /sbin/mii-tool ] && /sbin/mii-tool ${cureth} 2>/dev/null | grep -qF 'no link'
464                                 then
465                                         linkstate='no-link'
466                                 else # if not sure, set linkstate='unknown'
467                                         linkstate='unknown'
468                                 fi
469                                 echo "--- ${cureth}: link=${linkstate}, mac=${mac}"
470
471                                 # If the link is up, then try (even if another interface already has a dhcp address)
472                                 if [ "${linkstate}" != 'no-link' ] 
473                                 then
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}"
477                                         ${cmd} ; res="$?"
478                                         echo "${cmd} --> ${res}"
479                                         [ "${res}" = '0' ] && dhcpstate='ok'
480                                 fi
481                         done
482
483                         if [ "${dhcpstate}" != 'ok' ]
484                         then
485                                 echo "Cannot get a DHCP address. Check the cables on the ethernet interfaces."
486                                 sleep 2
487                         fi
488                 done
489         fi
490
491         # ---- configure the gateway if requested on cmdline ----
492         if [ -n "${SETGW}" ]
493         then
494                 while route del default gw 0.0.0.0 2>&-
495                 do
496                         echo "netconfig1: removing old default route"
497                 done
498                 echo "netconfig1: set new default route to ${SETGW}"
499                 route add default gw ${SETGW}
500         fi
501
502         # ---- configure the nameserver if requested on cmdline ----
503         if [ -n "${SETDNS}" ]
504         then
505                 rm -f /etc/resolv.conf 2>/dev/null
506                 echo "netconfig1: set nameserver to ${SETDNS}"
507                 echo "nameserver ${SETDNS}" > /etc/resolv.conf
508         fi
509 }
510
511 sysresccd_setup_volumes()
512 {
513         # Setup dmraid for fake raid devices
514         if [ -x "/sbin/dmraid-activate" ] && ! grep -q 'nodmraid' /proc/cmdline
515         then
516                 good_msg "Activating dmraid (fake hardware raid)..."
517                 if devices=$(dmraid -r -c)
518                 then
519                         for dev in $devices
520                         do
521                                 dmraid-activate $dev
522                         done
523                 fi
524         fi
525
526         # Setup mdadm for linux software raid
527         if [ -x "/sbin/mdadm" ] && ! grep -q 'nomdadm' /proc/cmdline
528         then
529                 good_msg "Loading MD modules for software raid..."
530                 for mod in linear multipath raid0 raid1 raid456 raid5 raid6 raid10
531                 do
532                         modprobe -q ${mod}
533                 done
534                 good_msg "Starting mdadm (linux software raid)"
535                 /sbin/mdadm -Es > /etc/mdadm.conf
536                 /sbin/mdadm -As
537         fi
538
539         # Setup the Logical Volume Manager
540         if [ -x "/sbin/lvm" ] && ! grep 'nolvm' /proc/cmdline
541         then
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
545         fi
546 }
547
548 # ============================================================================================================
549
550 sysresccd_chroot()
551 {
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' ]
559         then
560                 sysresccd_panic "You must boot with a 64bit kernel such as rescue64 to run ${INITPROG}"
561         fi
562
563         # move /dev to the new root filesystem
564         mount -n -o move /dev ${NEWROOT}/dev
565         nuke /dev
566         ln -s ${NEWROOT}/dev /dev
567
568         if [ ! -x ${NEWROOT}${INITPROG} ]
569         then
570                 sysresccd_panic "${INITPROG} not found on root filesystem"
571         fi
572
573         umount /proc
574         umount /sys
575
576         good_msg "Executing ${INITPROG} from the root filesystem..."
577         exec run-init ${NEWROOT} ${INITPROG} <${NEWROOT}/dev/console >${NEWROOT}/dev/console
578
579         # ------------------------------- minishell -------------------------------
580         sysresccd_panic "Failed to run run-init ${NEWROOT} ${INITPROG}"
581 }
582
583 # ============================================================================================================
584 # ============================================================================================================
585
586 sysresccd_stage1_http()
587 {
588         if ! mount -t tmpfs -o ${CACHESIZE} tmpfs ${BOOTPATH}
589         then
590                 sysresccd_panic "Cannot create tmpfs on ${BOOTPATH}"
591         fi
592
593         if ! echo "${HTTPBOOT}" | grep -q '^http://'
594         then
595                 sysresccd_panic "You requested an http boot, the address is not a valid http:// url."
596         fi
597
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}
601         res1=$?
602         /bin/busybox wget ${HTTPBOOT} -O ${BOOTPATH}/${LOOPDAT}
603         res2=$?
604
605         if [ ${res1} -ne 0 ] || [ ${res2} -ne 0 ]
606         then
607                 sysresccd_panic "Cannot download the files: wget failed. May be due to lack of memory"
608         fi
609
610         if [ ! -f "${BOOTPATH}/${LOOPDAT}" ]
611         then
612                 sysresccd_panic "Cannot download the \"${LOOPDAT}\" boot file."
613         fi
614
615         md5now=$(/bin/busybox md5sum ${BOOTPATH}/${LOOPDAT} | cut -d ' ' -f1)
616         md5orig=$(cat ${BOOTPATH}/${LOOPMD5} | cut -d ' ' -f1)
617         if [ "$md5now" = "$md5orig" ]
618         then
619                 good_msg "Downloaded boot file to \"${BOOTPATH}/${LOOPDAT}\""
620         else
621                 sysresccd_panic "The root filesystem image is invalid: md5sum failed"
622         fi
623 }
624
625 sysresccd_stage1_tftp()
626 {
627         if ! mount -t tmpfs -o ${CACHESIZE} tmpfs ${BOOTPATH}
628         then
629                 sysresccd_panic "Cannot create tmpfs on ${BOOTPATH}"
630         fi
631
632         if ! echo "${TFTPBOOT}" | grep -q '^tftp://'
633         then
634                 sysresccd_panic "You requested an tftp boot, the address is not a valid tftp:// url."
635         fi
636
637         good_msg "Downloading ${LOOPDAT} from ${TFTPBOOT}"
638         url="$(echo ${TFTPBOOT} | sed 's!tftp://!!g')" # remote the 'tftp://' prefix
639         tftpip="${url%%/*}"
640         tftpurl="/${url#*/}"
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}"
643         echo "$cmd1"
644         ${cmd1} ; res1="$?"
645         cmd2="/bin/busybox tftp -g -r ${tftpurl} -l ${BOOTPATH}/${LOOPDAT} ${tftpip}"
646         echo "$cmd2"
647         ${cmd2} ; res2="$?"
648
649         if [ "$res1" != '0' ] || [ "$res2" != '0' ]
650         then
651                 sysresccd_panic "Cannot download the files, wget failed. May be due to lack of memory"
652         fi
653
654         if [ ! -f "${BOOTPATH}/${LOOPDAT}" ]
655         then
656                 sysresccd_panic "Cannot download the \"${LOOPDAT}\" boot file."
657         fi
658
659         md5now=$(/bin/busybox md5sum ${BOOTPATH}/${LOOPDAT} | cut -d ' ' -f1)
660         md5orig=$(cat ${BOOTPATH}/${LOOPMD5} | cut -d ' ' -f1)
661         if [ "$md5now" = "$md5orig" ]
662         then
663                 good_msg "Downloaded boot file to \"${BOOTPATH}/${LOOPDAT}\""
664         else
665                 sysresccd_panic "The root filesystem image is invalid: md5sum failed"
666         fi
667 }
668
669 sysresccd_stage1_nfs()
670 {
671         nfsurl=$(echo ${NFSBOOT} | sed -e 's!nfs://!!g')
672
673         good_msg "Mouting the NFS filesystem from ${NFSBOOT}"
674         cmd="mount -t nfs -o intr,nolock ${nfsurl} ${BOOTPATH}"
675         if ! ${cmd}
676         then
677                 sysresccd_panic "Cannot mount NFS: ${cmd}"
678         fi
679         good_msg "Successfully mounted the NFS filesystem"
680
681         if [ ! -f "${BOOTPATH}/${SUBDIR}/${LOOPDAT}" ]
682         then
683                 sysresccd_panic "Cannot find the \"${SUBDIR}/${LOOPDAT}\" boot file."
684         fi
685
686         md5now=$(/bin/busybox md5sum ${BOOTPATH}/${SUBDIR}/${LOOPDAT} | cut -d ' ' -f1)
687         md5orig=$(cat ${BOOTPATH}/${SUBDIR}/${LOOPMD5} | cut -d ' ' -f1)
688         if [ "$md5now" = "$md5orig" ]
689         then
690                 good_msg "Successfully checked md5 sum of ${BOOTPATH}/${LOOPDAT}"
691         else
692                 sysresccd_panic "md5sum checksum is invalid on the root filesystem image"
693         fi
694 }
695
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
698 {
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'
703
704         case "${devtype}" in
705         auto) # all devices
706                 searchdevices=$(sysresccd_expand_alldevices ${BLKDEVICES})
707                 ;;
708         rmdev) # removable devices only
709                 searchdevices=$(sysresccd_expand_removable ${BLKDEVICES})
710                 ;;
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}" ]
715                 then
716                         searchdevices="${target}"
717                 elif [ -b "/dev/disk/by-uuid/${uuid}" ]
718                 then
719                         searchdevices="/dev/disk/by-uuid/${uuid}"
720                 fi
721                 ;;
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}" ]
726                 then
727                         searchdevices="${target}"
728                 elif [ -b "/dev/disk/by-label/${uuid}" ]
729                 then
730                         searchdevices="/dev/disk/by-label/${uuid}"
731                 fi
732                 ;;
733         *) # specific device name (eg: "/dev/sda1")
734                 searchdevices="${devtype}"
735                 ;;
736         esac
737
738         SEARCHDEVICE='' # result returned
739         mkdir -p ${mountdir}
740         for curdev in ${searchdevices}
741         do
742                 if [ -b "${curdev}" ] # Check for a block device to mount
743                 then
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} "
747                         then
748                                 good_msg "Skipping mount on device: ${curdev}"
749                         else
750                                 good_msg "Attempting to mount device: ${curdev}"
751
752                                 for curfs in vfat msdos iso9660 ntfs auto
753                                 do
754                                         case "${curfs}" in
755                                                 iso9660)
756                                                         mntopt='-o mode=0644'
757                                                         ;;
758                                                 vfat)
759                                                         mntopt='-o fmask=0133'
760                                                         ;;
761                                                 *)
762                                                         mntopt=''
763                                                         ;;
764                                         esac
765
766                                         if mount -r -t ${curfs} ${curdev} ${mountdir} ${mntopt} >/dev/null 2>&1
767                                         then
768                                                 if [ -e ${mountdir}/${filepath} ]
769                                                 then
770                                                         SEARCHDEVICE="${curdev}"
771                                                         good_msg "File ${filepath} found on device ${curdev}"
772                                                         if [ "${mountmode}" = 'rw' ] && ! mount -o remount,rw,noatime ${mountdir}
773                                                         then
774                                                                 sysresccd_panic "Cannot remount ${curdev} in read-write mode"
775                                                         fi
776                                                         return 0
777                                                 else
778                                                         umount ${mountdir} >/dev/null 2>&1
779                                                 fi
780                                         fi
781                                 done
782                         fi
783                 fi
784         done
785         return 1
786 }
787
788 # find the device which contains sysrcd.dat and mount it on ${BOOTPATH}
789 sysresccd_stage1_normal()
790 {
791         good_msg "Searching for ${SUBDIR}/${LOOPDAT} on devices..."
792         filefound=''
793         for attempts in 1 2 3 4 5
794         do
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'
797                 then
798                         if [ "${DOCHECK}" = '1' ] # don't run checksum by default on slow medias (cdrom, usb, ...)
799                         then
800                                 if [ ! -f "${BOOTPATH}/${SUBDIR}/${LOOPMD5}" ]
801                                 then
802                                         bad_msg "Cannot find md5 checksum file: ${LOOPMD5}"
803                                 else
804                                         md5now=$(/bin/busybox md5sum ${BOOTPATH}/${SUBDIR}/${LOOPDAT} | cut -d ' ' -f1)
805                                         md5orig=$(cat ${BOOTPATH}/${SUBDIR}/${LOOPMD5} | cut -d ' ' -f1)
806                                         if [ "$md5now" = "$md5orig" ]
807                                         then
808                                                 good_msg "md5 checksum of ${LOOPDAT} successfully checked"
809                                         else
810                                                 sysresccd_panic "md5sum checksum is invalid on the root filesystem image"
811                                         fi
812                                 fi
813                         fi
814                         filefound='1'
815                         break
816                 fi
817         done
818
819         if [ -z "${filefound}" ]
820         then
821                 sysresccd_panic "Cannot find ${SUBDIR}/${LOOPDAT} on devices"
822         fi
823
824         if [ "${DOCACHE}" = '1' ]
825         then
826                 good_msg "Creating tmpfs for caching in ${CACHEDIR}"
827                 if ! mount -t tmpfs -o ${CACHESIZE} tmpfs ${CACHEDIR}
828                 then
829                         sysresccd_panic "Cannot mount tmpfs filesystem on ${CACHEDIR} for caching"
830                 fi
831
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
836
837                 # --------------- Cache autorun files
838                 autoruns="$(ls -d ${BOOTPATH}/${SUBDIR}/autorun* 2>/dev/null)"
839                 [ "$autoruns" != "" ] && cp $autoruns ${CACHEDIR}/
840
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
846
847                 # --------------- Check main loop file
848                 expectedsize=$(/bin/busybox stat -c%s "${BOOTPATH}/${SUBDIR}/${LOOPDAT}")
849                 copiedsize=$(/bin/busybox stat -c%s "${CACHEDIR}/${LOOPDAT}")
850
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
856                         sleep 3
857                 else # docache successful
858                         good_msg "File ${LOOPDAT} successfully cached"
859                         SUBDIR=''
860
861                         # cache other files if possible
862                         if [ -z "${LOWMEM}" ] && [ -d ${BOOTPATH}/${SUBDIR}/isolinux ] && [ -d ${BOOTPATH}/${SUBDIR}/bootdisk ] && [ -d ${BOOTPATH}/${SUBDIR}/ntpasswd ]
863                         then
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
866                                 then
867                                     rm -rf ${CACHEDIR}/{isolinux,bootdisk,ntpasswd}
868                                     bad_msg "Cannot cache isolinux and bootdisk. Likely due to lack of memory"
869                                 fi
870                         fi
871
872                         # unmount the media if possible
873                         if umount ${BOOTPATH}
874                         then
875                                 good_msg "The original media has been unmounted"
876                                 cmd="mount -n --move ${CACHEDIR} ${BOOTPATH}"
877                                 if ! ${cmd}
878                                 then
879                                         bad_msg "${cmd} --> ${res}" && sleep 3
880                                 fi
881                         else
882                                 bad_msg "Cannot unmount the original media"
883                         fi
884
885                         # unmount isostore if necessary
886                         if cat /proc/mounts | awk '{print $2}' | grep -q "^${ISOSTORE}$"
887                         then
888                                 if losetup -d /dev/loop0
889                                 then
890                                         umount ${ISOSTORE} && good_msg "Unmounted ${ISOSTORE}" || bad_msg "Cannot unmount ${ISOSTORE}"
891                                 fi
892                         fi
893                 fi
894         fi
895 }
896
897 sysresccd_stage2_nbd()
898 {
899         nbdurl=$(echo ${NBDBOOT} | sed -e 's!nbd://!!g')
900         NBD_SERVER=$(echo "${nbdurl}" | sed 's/:.*//')
901         NBD_PORT=$(echo "${nbdurl}" | sed 's/.*://')
902
903         REAL_ROOT="nbd"
904         NBD_DEVICE="/dev/nbd0"
905         NBD_PROG="/sbin/nbd-client"
906
907         if [ ! -x "${NBD_PROG}" ]
908         then
909                 sysresccd_panic "Error: program ${NBD_PROG} not found"
910         fi
911
912         if ! modprobe nbd
913         then
914                 sysresccd_panic "Error: cannot load nbd kernel module"
915         fi
916
917         good_msg "Setting up the NBD boot device..."
918         if ! ${NBD_PROG} "${NBD_SERVER}" "${NBD_PORT}" "${NBD_DEVICE}" -persist
919         then
920                 sysresccd_panic "Error: nbd-client failed to connect to ${NBD_SERVER}:${NBD_PORT}"
921         else
922                 good_msg "nbd-client successfully connected to ${NBD_SERVER}:${NBD_PORT}"
923         fi
924
925         cmd="mount -t squashfs -o ro ${NBD_DEVICE} ${SQUASHFSMNT}"
926         if ! ${cmd}
927         then
928                 sysresccd_panic "ERROR: Cannot mount ${NBD_DEVICE}. ${cmd}"
929         else
930                 good_msg "successfully mounted ${NBD_DEVICE} on ${SQUASHFSMNT}"
931         fi
932 }
933
934 sysresccd_stage2_normal() # mount ${BOOTPATH}/sysrcd.dat on ${SQUASHFSMNT}
935 {
936         good_msg "Mounting the squashfs root filesystem on ${SQUASHFSMNT}"
937
938         mountok=''
939         squashfsimg="${BOOTPATH}/${SUBDIR}/${LOOPDAT}"
940         for fs in '-t squashfs' ''
941         do
942                 if [ "$mountok" != "ok" ]
943                 then
944                         mount ${fs} ${squashfsopt} -o ro ${squashfsimg} ${SQUASHFSMNT} 2>/dev/null && mountok='ok'
945                 fi
946         done
947
948         if [ "$mountok" != "ok" ]
949         then
950                 sysresccd_panic "ERROR: Cannot mount ${LOOPDAT}. Kernel version [$(uname -a)]"
951         fi
952 }
953
954 sysresccd_stage3_normal() # "backstore" + "aufs" + "mount --move"
955 {
956         # 1. search for a backstore file ("sysrcd.bs" by default)
957         BACKSTORE_FOUND=''
958         if [ "${BACKSTORE_CMD}" != 'off' ]
959         then
960                 BACKSTORE_DEVTYPE='rmdev' # by default search backstores only on removable devices
961                 for curopt in $(echo ${BACKSTORE_CMD} | sed -e 's!,! !g')
962                 do
963                         case "${curopt}" in
964                                 alldev)
965                                         BACKSTORE_DEVTYPE='auto' # search for backstores on all types of devices
966                                         ;;
967                                 *)
968                                         BACKSTORE_DAT=${curopt} # search for backstores on that particular device
969                                         ;;
970                         esac
971                 done
972
973                 good_msg "Searching for ${SUBDIR}/${BACKSTORE_DAT} on devices..."
974                 if sysresccd_find_file ${BACKSTORE_DEVTYPE} ${SUBDIR}/${BACKSTORE_DAT} ${BACKSTORE_MNT} 'rw'
975                 then
976                         good_msg "Backing store ${SUBDIR}/${BACKSTORE_DAT} found on ${SEARCHDEVICE}"
977                         if ! mount ${BACKSTORE_MNT}/${SUBDIR}/${BACKSTORE_DAT} ${BACKSTORE_MEM}
978                         then
979                                 sysresccd_panic "Cannot mount the loopback backstore file ${SUBDIR}/${BACKSTORE_DAT}"
980                         fi
981                         BACKSTORE_FOUND='1'
982                 fi
983         fi
984
985         # 2. store modifications in a tmpfs filesystem if there is no backstore
986         if [ -z "${BACKSTORE_FOUND}" ] && ! mount -t tmpfs tmpfs ${BACKSTORE_MEM}
987         then
988                 sysresccd_panic "Fatal error: cannot mount tmpfs on ${BACKSTORE_MEM}"
989         fi
990
991         # 3. create the aufs filesystem
992         if ! grep -q aufs /proc/filesystems
993         then
994                 sysresccd_panic "Fatal error: aufs filesystem not supported by the kernel."
995         fi
996         if mount -t aufs none ${NEWROOT} -o dirs=${BACKSTORE_MEM}=rw:${SQUASHFSMNT}=ro -o noatime
997         then
998                 good_msg "The aufs filesystem has been created"
999         else
1000                 sysresccd_panic "Fatal error: cannot mount the aufs filesystem."
1001         fi
1002
1003         # 4. copy cached autorun scripts
1004         autoruns="$(ls -d ${CACHEDIR}/autorun* 2>/dev/null)"
1005         [ "$autoruns" != "" ] && cp $autoruns ${NEWROOT}/var/autorun/cdrom
1006
1007         # 5. move filesystems mount points to the newroot
1008         for mntdir in ${BOOTPATH} ${SQUASHFSMNT} ${BACKSTORE_MNT} ${BACKSTORE_MEM} ${ISOSTORE}
1009         do
1010                 targetdir="${NEWROOT}/livemnt/${mntdir}"
1011                 if cat /proc/mounts | awk '{print $2}' | grep -q "^${mntdir}$"
1012                 then
1013                         mkdir -p ${targetdir} 2>/dev/null
1014                         cmd="mount -n --move ${mntdir} ${targetdir}"
1015                         if ! ${cmd}
1016                         then
1017                                 sysresccd_panic "${cmd} failed"
1018                         fi
1019                 fi
1020         done
1021
1022         # make directories
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
1026         do
1027                 mkdir -p "${NEWROOT}${curdir}"
1028         done
1029
1030         if [ -e /etc/sysconfig/keyboard ]
1031         then
1032                 mkdir -p ${NEWROOT}/etc/sysconfig/
1033                 cp /etc/sysconfig/keyboard ${NEWROOT}/etc/sysconfig/keyboard
1034         fi
1035
1036         # if option "lowmem" was enabled then do not start these initscripts
1037         if [ "${LOWMEM}" = '1' ]
1038         then
1039                 for initscr in sshd nfs portmap
1040                 do
1041                         rm -f "${NEWROOT}/etc/runlevels/default/${initscr}"
1042                 done
1043         fi
1044 }
1045
1046 sysresccd_stage3_rootsys() # mount the root partition on ${SQUASHFSMNT}
1047 {
1048         good_msg "Searching a root filesystem having ${INITPROG}"
1049
1050         filefound=''
1051         for attempts in 1 2 3 4 5
1052         do
1053                 [ ${attempts} -gt 1 ] && sleep 3 && bad_msg "Cannot find device with ${INITPROG}. Retrying..."
1054                 if sysresccd_find_file ${ROOTOPT} ${INITPROG} ${NEWROOT} 'rw'
1055                 then
1056                         filefound='1'
1057                         break
1058                 fi
1059         done
1060
1061         if [ -z "${filefound}" ]
1062         then
1063                 sysresccd_panic "Cannot find a valid root filesystem (partition having ${INITPROG})"
1064         fi
1065
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}/
1070 }
1071
1072 sysresccd_stage0_isoloop() # losetup the iso image on /dev/loop0
1073 {
1074         good_msg "Searching for ${SUBDIR}/${ISOLOOP} on devices..."
1075         filefound=''
1076         for attempts in 1 2 3 4 5
1077         do
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'
1080                 then
1081                         filefound='1'
1082                         break
1083                 fi
1084         done
1085
1086         if [ -z "${filefound}" ]
1087         then
1088                 sysresccd_panic "Cannot find device with ${SUBDIR}/${ISOLOOP}"
1089         fi
1090
1091         if losetup /dev/loop0 ${ISOSTORE}/${SUBDIR}/${ISOLOOP}
1092         then
1093                 good_msg "Loopback device configured with ${ISOSTORE}/${SUBDIR}/${ISOLOOP}"
1094         else
1095                 bad_msg "Cannot configure /dev/loop0 with ${ISOSTORE}/${SUBDIR}/${ISOLOOP}"
1096         fi
1097 }
1098
1099 # =============================================================================
1100
1101 sysresccd_stage0() # special preparations for isoroot
1102 {
1103         case "${STAGE0}" in
1104                 isoloop)
1105                         sysresccd_stage0_isoloop
1106                         STAGE1='normal'
1107                         ;;
1108                 *)
1109                         STAGE1="${STAGE0}"
1110                         ;;
1111         esac
1112 }
1113
1114 sysresccd_stage1() # find sysrcd.dat and put it in ${BOOTPATH}
1115 {
1116         case "${STAGE1}" in
1117                 rootsys)
1118                         STAGE2="rootsys"
1119                         ;;
1120                 nbd)
1121                         STAGE2="nbd"
1122                         ;;
1123                 http)
1124                         sysresccd_stage1_http
1125                         STAGE2="normal"
1126                         ;;
1127                 tftp)
1128                         sysresccd_stage1_tftp
1129                         STAGE2="normal"
1130                         ;;
1131                 nfs)
1132                         sysresccd_stage1_nfs
1133                         STAGE2="normal"
1134                         ;;
1135                 normal)
1136                         sysresccd_stage1_normal
1137                         STAGE2="normal"
1138                         ;;
1139         esac
1140 }
1141
1142 sysresccd_stage2() # mount ${BOOTPATH}/sysrcd.dat on ${SQUASHFSMNT}
1143 {
1144         case "${STAGE2}" in
1145                 rootsys)
1146                         STAGE3="rootsys"
1147                         ;;
1148                 nbd)
1149                         sysresccd_stage2_nbd
1150                         STAGE3="normal"
1151                         ;;
1152                 normal)
1153                         sysresccd_stage2_normal
1154                         STAGE3="normal"
1155                         ;;
1156         esac
1157 }
1158
1159 sysresccd_stage3() # ${NEWROOT}=aufs
1160 {
1161         case "${STAGE3}" in
1162                 rootsys)
1163                         sysresccd_stage3_rootsys
1164                         ;;
1165                 normal)
1166                         sysresccd_stage3_normal
1167                         ;;
1168         esac
1169 }
1170
1171 # =============================================================================
1172
1173 sysresccd_parsecmdline()
1174 {
1175         for x in $(cat /proc/cmdline)
1176         do
1177                 case "${x}" in
1178                 init\=*)
1179                         INITPROG=`parse_opt "${x}"`
1180                         ;;
1181                 ethx\=*)
1182                         SETETHX=`parse_opt "${x}"`
1183                         DODHCP=''
1184                         NETCONFIG='1'
1185                         ;;
1186                 dodhcp)
1187                         DODHCP='1'
1188                         SETETHX=''
1189                         NETCONFIG='1'
1190                         ;;
1191                 dns\=*)
1192                         SETDNS=`parse_opt "${x}"`
1193                         NETCONFIG='1'
1194                         ;;
1195                 gw\=*)
1196                         SETGW=`parse_opt "${x}"`
1197                         NETCONFIG='1'
1198                         ;;
1199                 gateway\=*)
1200                         SETGW=`parse_opt "${x}"`
1201                         NETCONFIG='1'
1202                         ;;
1203                 dhcphostname\=*)
1204                         DHCPHOSTNAME=`parse_opt "${x}"`
1205                         NETCONFIG='1'
1206                         ;;
1207                 netboot\=http://*)
1208                         HTTPBOOT=`parse_opt "${x}"`
1209                         STAGE0='http'
1210                         NETCONFIG='1'
1211                         ;;
1212                 netboot\=tftp://*)
1213                         TFTPBOOT=`parse_opt "${x}"`
1214                         STAGE0='tftp'
1215                         NETCONFIG='1'
1216                         ;;
1217                 netboot\=nfs://*)
1218                         NFSBOOT=`parse_opt "${x}"`
1219                         STAGE0='nfs'
1220                         NETCONFIG='1'
1221                         ;;
1222                 netboot\=nbd://*)
1223                         NBDBOOT=`parse_opt "${x}"`
1224                         STAGE0='nbd'
1225                         NETCONFIG='1'
1226                         ;;
1227                 root\=*)
1228                         ROOTOPT=`parse_opt "${x}"`
1229                         STAGE0='rootsys'
1230                         ;;
1231                 isoloop\=*)
1232                         ISOLOOP=`parse_opt "${x}"`
1233                         STAGE0='isoloop'
1234                         ;;
1235                 docache)
1236                         DOCACHE='1'
1237                         ;;
1238                 subdir\=*)
1239                         SUBDIR=`parse_opt "${x}"`
1240                         ;;
1241                 speakup\=*)
1242                         SPEAKUP=`parse_opt "${x}"`
1243                         ;;
1244                 backstore\=*)
1245                         BACKSTORE_CMD=`parse_opt "${x}"`
1246                         ;;
1247                 setkmap\=*)
1248                         SETKMAP=`parse_opt "${x}"`
1249                         ;;
1250                 scandelay\=*)
1251                         SCANDELAY=`parse_opt "${x}"`
1252                         ;;
1253                 scandelay)
1254                         SCANDELAY=10
1255                         ;;
1256                 doload\=*)
1257                         MODLOAD=`parse_opt "${x}"`
1258                         MODLOAD="`echo ${MODLOAD} | sed -e \"s/,/ /g\"`"
1259                         ;;
1260                 nodetect)
1261                         NODETECT='1'
1262                         ;;
1263                 noload\=*)
1264                         BLACKLIST=`parse_opt "${x}"`
1265                         BLACKLIST="`echo ${BLACKLIST} | sed -e \"s/,/ /g\"`"
1266                         ;;
1267                 CONSOLE\=*)
1268                         CONSOLE=`parse_opt "${x}"`
1269                         exec >${CONSOLE} <${CONSOLE} 2>&1
1270                         ;;
1271                 docheck)
1272                         DOCHECK='1'
1273                         ;;
1274                 lowmem)
1275                         LOWMEM='1'
1276                         ;;
1277                 minishell)
1278                         MINISHELL='1'
1279                         ;;
1280                 httpboot\=*) # for compatibility only
1281                         HTTPBOOT=`parse_opt "${x}"`
1282                         STAGE0='http'
1283                         NETCONFIG='1'
1284                         ;;
1285                 tftpboot\=*) # for compatibility only
1286                         TFTPBOOT=`parse_opt "${x}"`
1287                         STAGE0='tftp'
1288                         NETCONFIG='1'
1289                         ;;
1290                 boothttp\=*) # for compatibility only
1291                         HTTPBOOT=`parse_opt "${x}"`
1292                         STAGE0='http'
1293                         NETCONFIG='1'
1294                         ;;
1295                 boottftp\=*) # for compatibility only
1296                         TFTPBOOT=`parse_opt "${x}"`
1297                         STAGE0='tftp'
1298                         NETCONFIG='1'
1299                         ;;
1300                 nfsboot\=*) # for compatibility only
1301                         ARG=`parse_opt "${x}"`
1302                         NFSBOOT="nfs://${ARG}"
1303                         STAGE0='nfs'
1304                         NETCONFIG='1'
1305                         ;;
1306                 nbdboot\=*) # for compatibility only
1307                         ARG=`parse_opt "${x}"`
1308                         NBDBOOT="nbd://${ARG}"
1309                         STAGE0='nbd'
1310                         NETCONFIG='1'
1311                         ;;
1312                 esac
1313         done
1314 }
1315
1316 # =============================================================================
1317
1318 sysresccd_init()
1319 {
1320         export PATH=/bin:/usr/bin:/sbin:/usr/sbin
1321
1322         # only run as an init program
1323         if [ "$$" != '1' ]
1324         then
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".'
1328                 exit 1
1329         fi
1330
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}
1348
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
1352
1353         # setup busybox
1354         /bin/busybox --install -s
1355 }
1356
1357 # =============================================================================
1358
1359 NORMAL="\033[0m"
1360 WARN="\033[33;1m"
1361 BAD="\033[31;1m"
1362 BOLD="\033[1m"
1363 GOOD="\033[32;1m"
1364
1365 DOCACHE=''
1366 SETKMAP=''
1367 MINISHELL=''
1368 NETCONFIG=''
1369 DHCPHOSTNAME=''
1370 DOCHECK=''
1371 LOWMEM=''
1372 SETGW=''
1373 SETDNS=''
1374 SETETHX=''
1375 NETBOOT=''
1376 NFSBOOT=''
1377 NBDBOOT=''
1378 ISOLOOP=''
1379 ISOLOOPDEV=''
1380 DODHCP=''
1381 ROOTFS=''
1382 SUBDIR=''
1383 SPEAKUP=''
1384 STAGE0='normal'
1385 BOOTPATH='/boot'
1386 NEWROOT='/newroot'
1387 SQUASHFSMNT='/squashfs'
1388 ISOSTORE='/isostore'
1389 BACKSTORE_CMD=''
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'
1397 CACHEDIR='/cache'
1398 CACHESIZE='size=512m'
1399
1400 # CDROM DEVICES
1401 BLKDEVICES="/dev/cdroms/* /dev/ide/cd/* /dev/sr*"
1402 # USB Keychain/Storage
1403 BLKDEVICES="$BLKDEVICES /dev/sd*"
1404 # IDE devices
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/*"
1410 # iSeries devices
1411 BLKDEVICES="$BLKDEVICES /dev/iseries/vcd*"
1412 # HP Smart Array
1413 BLKDEVICES="$BLKDEVICES /dev/cciss* /dev/cciss/*"
1414 # devmapper
1415 BLKDEVICES="$BLKDEVICES /dev/dm* /dev/mapper/*"
1416
1417 # =============================================================================
1418
1419 sysresccd_init
1420 sysresccd_parsecmdline
1421 sysresccd_terminal
1422 sysresccd_udev_start
1423 sysresccd_speakup
1424 sysresccd_setup_keymap
1425 sysresccd_setup_volumes
1426 sysresccd_netconfig
1427 sysresccd_debug
1428 sysresccd_stage0
1429 sysresccd_stage1
1430 sysresccd_stage2
1431 sysresccd_stage3
1432 sysresccd_udev_stop
1433 sysresccd_chroot
1434