Imported Debian patch 3.4-9
[debian/elilo] / debian / elilo.sh
1 #! /bin/sh
2
3 ###############################################################################
4 ##
5 ## elilo installs efi bootloader onto a bootstrap partition (based on ybin)
6 ## Copyright (C) 2001 Ethan Benson
7 ##
8 ## This program is free software; you can redistribute it and/or
9 ## modify it under the terms of the GNU General Public License
10 ## as published by the Free Software Foundation; either version 2
11 ## of the License, or (at your option) any later version.
12 ##
13 ## This program is distributed in the hope that it will be useful,
14 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ## GNU General Public License for more details.
17 ##
18 ## You should have received a copy of the GNU General Public License
19 ## along with this program; if not, write to the Free Software
20 ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 ##
22 ###############################################################################
23
24 PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
25 ## allow to run out of /target in boot-floppies
26 if [ -n "$PATH_PREFIX" ] ; then
27     PATH="${PATH}:${PATH_PREFIX}/sbin:${PATH_PREFIX}/bin:${PATH_PREFIX}/usr/sbin:${PATH_PREFIX}/usr/bin:${PATH_PREFIX}/usr/local/sbin:${PATH_PREFIX}/usr/local/bin"
28 fi
29 PRG="${0##*/}"
30 SIGINT="$PRG: Interrupt caught ... exiting"
31 VERSION=##VERSION##
32 DEBUG=0
33 VERBOSE=0
34 TMP="${TMPDIR:-/tmp}"
35 TARGET=
36 # Beware, /EFI/debian occurs with double backslashes in the script too
37 # so change those as well as EFIROOT, if need be.
38 EFIROOT=/EFI/debian
39 export LC_COLLATE=C
40
41 ## catch signals, clean up junk in /tmp.
42 trap "cleanup" 0
43 trap "cleanup; exit 129" HUP
44 trap "echo 1>&2 $SIGINT ; cleanup; exit 130" INT
45 trap "cleanup; exit 131" QUIT
46 trap "cleanup; exit 143" TERM
47
48 ## define default config file
49 CONF=/etc/elilo.conf
50 bootconf=$CONF
51 ERR=" Error in $CONF:"
52
53 ## define default configuration
54 boot=unconfigured
55
56 ## allow default to work on packaged and non-packaged elilo. 
57 if [ -f /usr/local/lib/elilo/elilo.efi ] ; then
58     install=/usr/local/lib/elilo/elilo.efi
59 elif [ -f /usr/lib/elilo/elilo.efi ] ; then
60     install=/usr/lib/elilo/elilo.efi
61 fi
62
63 ## defaults
64 efiboot=0
65 autoconf=0
66 fstype=vfat
67 umountproc=0
68
69 ## elilo autoconf defaults
70 label=Linux
71 timeout=20
72 root=/dev/sda3
73
74 # image default is controlled by /etc/kernel-img.conf, if it exists
75 if [ -f /etc/kernel-img.conf ] &&
76         grep -E -qi "^(image|link)_in_boot *= *yes" /etc/kernel-img.conf; then
77     image=/boot/vmlinuz
78     initrdline=initrd=/boot/initrd.img
79     initrdoldline=initrd=/boot/initrd.img.old
80 else
81     image=/vmlinuz
82     initrdline=initrd=/initrd.img
83     initrdoldline=initrd=/initrd.img.old
84 fi
85 if [ -f /etc/kernel-img.conf ] &&
86         ! grep -qi "^do_initrd *= *yes" /etc/kernel-img.conf; then
87     initrdline=
88     initrdoldline=
89 fi
90
91 ## make fake `id' if its missing, outputs 0 since if its missing we
92 ## are probably running on boot floppies and thus are root.
93 if (command -v id > /dev/null 2>&1) ; then 
94     true
95 else
96     id()
97     {
98     echo 0
99     }
100 fi
101
102 ## --version output
103 version()
104 {
105 echo \
106 "$PRG $VERSION
107 Written by Richard Hirst, based on work by Ethan Benson
108
109 This is free software; see the source for copying conditions.  There is NO
110 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
111 }
112
113 ## --help output.
114 usage()
115 {
116 echo \
117 "Usage: $PRG [OPTION]...
118 Update/install bootloader onto a bootstrap partition.
119
120   -b, --boot                 set bootstrap partition device [ -b /dev/sda1 ]
121   -i, --install              pathname to the actual bootloader binary
122                                default: /usr/{local/}lib/elilo/elilo.efi
123   -C, --config               use alternate configuration file [ -C config_file ]
124       --autoconf             auto-generate a /etc/elilo.conf
125       --efiboot              elilo auto configuration: create an efi boot
126                                manager entry for elilo
127       --timeout              elilo auto configuration: sets the time elilo
128                                will wait for user input before booting default
129                                image default: 20 (2 seconds)
130       --image                elilo auto configuration: sets the path to the
131                                kernel image. default: /vmlinuz
132       --label                elilo auto configuration: sets the image label
133                                default: Linux
134       --root                 elilo auto configuration: sets the root device
135                                default: /dev/sda3
136       --format               create a new FAT filesystem on the boot partition
137   -v, --verbose              make $PRG more verbose
138       --debug                print boring junk only useful for debugging
139   -h, --help                 display this help and exit
140   -V, --version              output version information and exit"
141 }
142
143 ## we have to do some things differently with a retarded devfs name.
144 ckdevfs()
145 {
146     case "$1" in
147         /dev/ide/*|/dev/scsi/*|/dev/discs/*)
148         return 0
149         ;;
150     *)
151         return 1
152         ;;
153     esac
154 }
155
156 ## the SmartArray RAID controllers use /dev/cciss/c0d0p1 kinds of names...
157 ckcciss()
158 {
159     case "$1" in
160         /dev/cciss/*)
161         return 0
162         ;;
163     *)
164         return 1
165         ;;
166     esac
167 }
168
169
170 ## configuration file parsing. FIXME: need a method which can parse
171 ## image= sections.
172 parseconf()
173 {
174 case "$1" in
175     str)
176        v=`grep "^$2[\ ,=]" "$CONF"` ; echo "${v#*=}"
177        ;;
178     flag)
179        grep "^$2\>" "$CONF" > /dev/null && echo 0 || echo 1
180        ;;
181     ck)
182        grep "^$2[\ ,=]" "$CONF" > /dev/null && echo 0 || echo 1
183        ;;
184 esac
185 }
186
187 ## check for existence of a configuration file, and make sure we have
188 ## read permission.
189 confexist()
190 {
191     if [ ! -e "$CONF" ] ; then
192         echo 1>&2 "$PRG: $CONF: No such file or directory"
193         return 1
194     elif [ ! -f "$CONF" ] ; then
195         echo 1>&2 "$PRG: $CONF: Not a regular file"
196         return 1
197     elif [ ! -r "$CONF" ] ; then
198         echo 1>&2 "$PRG: $CONF: Permission denied"
199         return 1
200     else
201         return 0
202     fi
203 }
204
205 ## check to make sure the configuration file is sane and correct.
206 ## maybe this is an insane ammount of error checking, but I want to
207 ## make sure (hopefully) nothing unexpected ever happens.  and i just
208 ## like useful errors from programs.  every error just marks an error
209 ## variable so we give the user as much info as possible before we
210 ## abandon ship.
211 checkconf()
212 {
213     if [ -L "$boot" ] ; then
214         oldboot=$boot
215         boot=$(readlink -f $oldboot)
216         echo 1>&2 "$PRG: $oldboot is a symbolic link, using $boot instead"
217     fi
218     if [ ! -e "$boot" ] ; then
219         echo 1>&2 "$PRG: $boot: No such file or directory"
220         CONFERR=1
221     elif [ ! -b "$boot" ] && [ ! -f "$boot" ] ; then
222         echo 1>&2 "$PRG: $boot: Not a regular file or block device"
223         CONFERR=1
224     elif [ ! -w "$boot" ] || [ ! -r "$boot" ] ; then
225         echo 1>&2 "$PRG: $boot: Permission denied"
226         CONFERR=1
227     fi
228
229     ## sanity check, make sure boot=bootstrap and not something dumb
230     ## like /dev/hda
231     case "$boot" in
232         *hda)
233             echo 1>&2 "$PRG:$ERR \`boot=$boot' would result in the destruction of all data on $boot"
234             CONFERR=1
235             ;;
236         *sda)
237             echo 1>&2 "$PRG:$ERR \`boot=$boot' would result in the destruction of all data on $boot"
238             CONFERR=1
239             ;;
240         *disc)
241             echo 1>&2 "$PRG:$ERR \`boot=$boot' would result in the destruction of all data on $boot"
242             CONFERR=1
243             ;;
244     esac
245
246     ## now make sure its not something dumb like the root partition
247     ROOT="$(v=`df / 2> /dev/null | grep ^/dev/` ; echo ${v%%[ ]*})"
248     BOOT="$(v=`df /boot 2> /dev/null | grep ^/dev/` ; echo ${v%%[ ]*})"
249     if [ "$boot" = "$ROOT" ] ; then
250         echo 1>&2 "$PRG:$ERR \`boot=$boot' would result in the destruction of the root filesystem"
251         CONFERR=1
252     elif [ "$boot" = "$BOOT" ] ; then
253         echo 1>&2 "$PRG:$ERR \`boot=$boot' would result in the destruction of the /boot filesystem"
254         CONFERR=1
255     fi
256
257     ## Make sure boot is not already mounted
258     mount | grep "^$boot " > /dev/null
259     if [ $? = 0 ] ; then
260         echo 1>&2 "$PRG: $boot appears to be mounted"
261         CONFERR=1
262     fi
263
264     if [ ! -e "$install" ] ; then
265         echo 1>&2 "$PRG: $install: No such file or directory"
266         CONFERR=1
267     elif [ ! -f "$install" ] ; then
268         echo 1>&2 "$PRG: $install: Not a regular file"
269         CONFERR=1
270     elif [ ! -r "$install" ] ; then
271         echo 1>&2 "$PRG: $install: Permission denied"
272         CONFERR=1
273     fi
274
275     if [ ! -e "$bootconf" ] ; then
276         echo 1>&2 "$PRG: $bootconf: No such file or directory"
277         CONFERR=1
278     elif [ ! -f "$bootconf" ] ; then
279         echo 1>&2 "$PRG: $bootconf: Not a regular file"
280         CONFERR=1
281     elif [ ! -r "$bootconf" ] ; then
282         echo 1>&2 "$PRG: $bootconf: Permission denied"
283         CONFERR=1
284     fi
285
286     if [ ! -d /proc/efi/vars ] && [ ! -d /sys/firmware/efi/vars ] && [ "$efiboot" = 1 ] ; then
287         echo 1>&2 "$PRG: no efi/vars under /proc or /sys/firmware, boot menu not updated"
288         efiboot=0
289     fi
290
291     if [ "$efiboot" = 1 ] ; then
292         ## see if efibootmgr exists and is executable
293         if (command -v efibootmgr > /dev/null 2>&1) ; then
294             [ -x `command -v efibootmgr` ] || MISSING=1 ; else MISSING=1
295         fi
296
297         if [ "$MISSING" = 1 ] ; then
298             efiboot=0
299             echo 1>&2 "$PRG: Warning: \`efibootmgr' could not be found, boot menu not updated"
300         fi
301
302         if [ -f "$boot" ] ; then
303             echo 1>&2 "$PRG: $boot is a regular file, disabling boot menu update"
304             efiboot=0
305         fi
306     fi
307
308     if [ "$CONFERR" = 1 ] ; then
309         return 1
310     else
311         return 0
312     fi
313 }
314
315
316 mnt()
317 {
318     ## we can even create bootstrap filesystem images directly if you
319     ## ever wanted too.
320     if [ -f "$boot" ] ; then
321         loop=",loop"
322     fi
323
324     if [ -e "$TMP/bootstrap.$$" ] ; then
325         echo 1>&2 "$PRG: $TMP/bootstrap.$$ exists, aborting."
326         return 1
327     fi
328
329     mkdir -m 700 "$TMP/bootstrap.$$"
330     if [ $? != 0 ] ; then
331         echo 1>&2 "$PRG: Could not create mountpoint directory, aborting."
332         return 1
333     fi
334
335     mount | grep "^$boot " > /dev/null
336     if [ $? = 0 ] ; then
337         echo 1>&2 "$PRG: $boot appears to be mounted! aborting."
338         return 1
339     fi
340
341     [ "$VERBOSE" = 1 ] && echo "$PRG: Mounting $boot..."
342     mount -t "$fstype" -o codepage=437,iocharset=iso8859-1,rw,noexec,umask=077$loop "$boot" "$TMP/bootstrap.$$"
343     if [ $? != 0 ] ; then
344         echo 1>&2 "$PRG: An error occured mounting $boot"
345         return 1
346     fi
347
348     TARGET="$TMP/bootstrap.$$"
349     return 0
350 }
351
352 copyfiles()
353 {
354     BTFILE=elilo.efi
355     CFFILE=elilo.conf
356     imagefiles=`grep '^image[[:space:]]*=' $bootconf | \
357                 sed 's/^image[[:space:]]*=[[:space:]]*//' | grep -v ':'`
358     initrdfiles=`grep '^[[:space:]]*initrd[[:space:]]*=' $bootconf | \
359                 sed 's/.*=[[:space:]]*//' | grep -v ':'`
360
361     ## Point of no return, removing the old EFI/debian tree
362     rm -rf $TARGET/$EFIROOT
363     if [ $? != 0 ]; then
364         echo 2>&1 "$PRG: Failed to delete old boot files, aborting"
365         return 1
366     fi
367     mkdir -p $TARGET/$EFIROOT
368
369     ## Add a README to warn that this tree is deleted every time elilo is run
370     echo -ne "\
371 This directory tree is managed by /usr/sbin/elilo, and is deleted and\n\
372 recreated every time elilo runs.  Any local changes will be lost.\n\
373 " > $TARGET/$EFIROOT/README.TXT
374
375     ## this is probably insecure on modern filesystems, but i think
376     ## safe on crippled hfs/dosfs.
377     [ "$VERBOSE" = 1 ] && echo "$PRG: Installing primary bootstrap $install onto $boot..."
378     cp -f "$install" "$TARGET/$EFIROOT/$BTFILE"
379     if [ $? != 0 ] ; then
380         echo 1>&2 "$PRG: An error occured while writing to $boot"
381         return 1
382     fi
383
384     [ "$VERBOSE" = 1 ] && echo "$PRG: Installing $bootconf on $boot..."
385     ## we comment out boot= and install=, because they are only really
386     ## needed in the /etc/elilo.conf file, and elilo.efi currently
387     ## doesn't understand them.  We also need to add /EFI/debian on to
388     ## the front of any paths that don't contain colons (device paths),
389     ## and replace tabs with spaces.
390     sed -e "s|^boot[[:space:]]*=|# &|" -e "s|^install[[:space:]]*=|# &|" \
391         -e "s|\t| |g" \
392         -e "s|\(^image[[:space:]]*=[[:space:]]*\)\([^:]*\)$|\1$EFIROOT\2|" \
393         -e "s|\(^[[:space:]]*initrd[[:space:]]*=[[:space:]]*\)\([^:]*\)$|\1$EFIROOT\2|" \
394         < "$bootconf" > "$TARGET/$EFIROOT/$CFFILE"
395     if [ $? != 0 ] ; then
396         echo 1>&2 "$PRG: An error occured while writing to $boot"
397         return 1
398     fi
399
400     [ "$DEBUG" = 1 ] && echo "----" && cat "$TARGET/$EFIROOT/$CFFILE" && echo "----"
401
402     for i in $imagefiles $initrdfiles; do
403         [ "$VERBOSE" = 1 ] && echo "$PRG: Installing $i on $boot..."
404         if [ -f $i ]; then
405             mkdir -p `dirname "$TARGET/$EFIROOT/$i"`
406             if [ $? != 0 ] ; then
407                 echo 1>&2 "$PRG: An error occured creating directory `dirname $EFIROOT/$i` on $boot"
408                 return 1
409             fi
410             cp -f "$i" "$TARGET/$EFIROOT/$i"
411             if [ $? != 0 ] ; then
412                 echo 1>&2 "$PRG: An error occured writing $i to $boot"
413                 return 1
414             fi
415         else
416             echo "$PRG: Warning: $i not found"
417         fi
418     done
419
420     sync ; sync
421
422     ## update the boot-device variable in EFI.
423     if [ "$efiboot" = 1 ] ; then
424         [ "$VERBOSE" = 1 ] && echo "$PRG: Updating EFI boot-device variable..."
425         efiquiet="-q"
426         [ "$VERBOSE" = 1 ] && efiquiet=""
427         if ckdevfs "$boot" ; then
428             BOOTDISK="${boot%/*}/disc"
429             BOOTPART="${boot##*part}"
430         elif ckcciss "$boot" ; then
431             BOOTDISK="${boot%p[0-9]*}"
432             BOOTPART="${boot##*[a-z]}"
433         else
434             BOOTDISK="${boot%%[0-9]*}"
435             BOOTPART="${boot##*[a-z]}"
436         fi
437         if [ -z "$BOOTDISK" ] || [ -z "$BOOTPART" ] ; then
438             echo 2>&1 "$PRG: Could not determine boot disk, aborting..."
439             return 1
440         fi
441
442         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: boot-disk      = $BOOTDISK"
443         [ "$DEBUG" = 1 ] && echo 1>&2 "$PRG: DEBUG: boot-partition = $BOOTPART"
444         # delete other entries with name "Debian GNU/Linux"
445         for b in `efibootmgr | grep "Debian GNU/Linux" | awk '{print substr($1,5,4) }'`; do
446             efibootmgr $efiquiet -b $b -B
447         done
448         # Add a new entry for this installation
449         efibootmgr $efiquiet -c -d $BOOTDISK -p $BOOTPART -w -L "Debian GNU/Linux" \
450                 -l \\EFI\\debian\\elilo.efi -u -- elilo -C \\EFI\\debian\\elilo.conf
451         if [ $? != 0 ] ; then
452             echo 1>&2 "$PRG: An error occured while updating boot menu, we'll ignore it"
453         fi
454         # Now, if 2nd and 3rd boot entries are for floppy and CD/DVD,
455         # move them up to 1st and 2nd, making our entry the 3rd.
456         bootorder=$(efibootmgr | sed -n 's/^BootOrder: \(.*\)$/\1/p')
457         boot1st=$(echo $bootorder | sed -n "s/\(....\).*$/\1/p")
458         boot2nd=$(echo $bootorder | sed -n "s/....,\(....\).*$/\1/p")
459         boot3rd=$(echo $bootorder | sed -n "s/....,....,\(....\).*$/\1/p")
460         boot456=$(echo $bootorder | sed -n "s/....,....,....\(.*\).*$/\1/p")
461         name2nd=$(efibootmgr | sed -n "s/^Boot$boot2nd[\*] \(.*\)$/\1/p")
462         name3rd=$(efibootmgr | sed -n "s/^Boot$boot3rd[\*] \(.*\)$/\1/p")
463         name23="@$name2nd@$name3rd"
464         if ( echo $name23 | grep -qi "@floppy" ); then
465             if ( echo $name23 | grep -qi "@cd") || ( echo $name23 | grep -qi "@dvd"); then
466                 efibootmgr $efiquiet -o $boot2nd,$boot3rd,$boot1st$boot456
467             fi
468         fi
469     fi
470
471     return 0
472 }
473
474 ## mkefifs function.
475 mkefifs()
476 {
477     mount | grep "^$boot\>" > /dev/null
478     if [ $? = 0 ] ; then
479         echo 1>&2 "$PRG: $boot appears to be mounted! aborting."
480         return 1
481     fi
482
483     if (command -v mkdosfs > /dev/null 2>&1) ; then
484         [ -x `command -v mkdosfs` ] || FAIL=1 ; else FAIL=1 ; fi
485         if [ "$FAIL" = 1 ] ; then
486             echo 1>&2 "$PRG: mkdosfs is not installed or cannot be found"
487             return 1
488         fi
489
490     [ "$VERBOSE" = 1 ] && echo "$PRG: Creating DOS filesystem on $boot..."
491     mkdosfs -n bootstrap "$boot" > /dev/null
492     if [ $? != 0 ] ; then
493         echo 1>&2 "$PRG: DOS filesystem creation failed!"
494         return 1
495     fi
496     return 0
497 }
498
499 mkconf()
500 {
501 ## defaults for this are defined at the beginning of the script with
502 ## other variables.
503
504 # We want to create an append= line from the current /proc/cmdline,
505 # so things like console=ttyS0 get picked up automatically.
506 # We also want to filter out bits of cmdline we are not interested in.
507
508 if [ -f /proc/cmdline ]; then
509   cmdline=`cat /proc/cmdline`
510 else
511   echo 1>&2 "$PRG: Warning: couldn't read /proc/cmdline, may need to add append=... to elilo.conf"
512   cmdline=""
513 fi
514
515 append=`echo $cmdline | tr ' ' '\n' | grep "^console=" | tr '\n' ' '`
516 if [ ! -z "$append" ]; then append="append=\"$append\""; fi
517
518 echo \
519 "## elilo configuration file generated by elilo $VERSION
520
521 install=$install
522 boot=$boot
523 delay=$timeout
524 default=$label
525 " > "$TMPCONF" || return 1
526
527 if [ -d /proc/sgi_sn ]
528 then
529   # aha!  This is an SGI Altix, and they need the relocatable option.
530   echo "relocatable" >> "$TMPCONF" || return 1
531 fi
532
533 echo \
534 "$append
535
536 image=$image
537         label=$label
538         root=$root
539         read-only
540         $initrdline
541
542 image=${image}.old
543         label=${label}OLD
544         root=$root
545         read-only
546         $initrdoldline
547 " >> "$TMPCONF" || return 1
548
549     ## Copy the new elilo.conf to /etc
550     if [ -f $CONF ]; then
551         echo 1>&2 "$PRG: backing up existing $CONF as ${CONF}-"
552         rm -f ${CONF}-
553         mv $CONF ${CONF}-
554     fi
555     cp -f "$TMPCONF" "$CONF"
556     if [ $? != 0 ] ; then
557         echo 1>&2 "$PRG: An error occured while writing to $conf"
558         return 1
559     fi
560
561 return 0
562 }
563
564 # check partition will be big enough for all we want to add to it
565
566 chkspace()
567 {
568     imagefiles=`grep '^image[[:space:]]*=' $bootconf | \
569                 sed 's/^image[[:space:]]*=[[:space:]]*//' | grep -v ':'`
570     initrdfiles=`grep '^[[:space:]]*initrd[[:space:]]*=' $bootconf | \
571                 sed 's/.*=[[:space:]]*//' | grep -v ':'`
572     bytesneeded=`cat $imagefiles $initrdfiles $install $bootconf 2>/dev/null | wc -c`
573     # convert to KB, allowing 5% overhead
574     kbneeded=$(( bytesneeded / 1024 + bytesneeded / 20480 ))
575     kbavailable=$(df -P -k $TARGET | sed -n "s|^$boot[[:space:]]\+[0-9]\+[[:space:]]\+[0-9]\+[[:space:]]\+\([0-9]\+\).*$|\1|p")
576     if [ -z $kbavailable ]; then
577         echo 2>&1 "$PRG: unable to determine space on $boot, aborting"
578         return 1
579     fi
580     if [ -d $TARGET/$EFIROOT ]; then
581         kbused=$(du -ks $TARGET/$EFIROOT | sed -n "s/[  ].*$//p")
582     else
583         kbused=0
584     fi
585     [ "$VERBOSE" = 1 ] && echo "$PRG: ${kbneeded}KB needed, ${kbavailable}KB free, ${kbused}KB to reuse"
586     kbavailable=$(( kbavailable + kbused ))
587     if [ "$kbavailable" -lt "$kbneeded" ] ; then
588         echo 1>&2 "$PRG: Insufficient space on $boot, need ${kbneeded}KB, only ${kbavailable}KB available"
589         return 1
590     fi
591 return 0
592 }
593
594
595 ## take out the trash.
596 cleanup()
597 {
598     if [ -n "$TARGET" ]; then
599         TARGET=
600         [ "$VERBOSE" = 1 ] && echo "$PRG: Unmounting $boot"
601         umount "$boot"
602         [ $? != 0 ] && echo 2>&1 "$PRG: Warning, failed to unmount $TARGET"
603     fi
604     if [ -n "$TMPCONF" ] ; then rm -f "$TMPCONF" ; fi
605     if [ -d "$TMP/bootstrap.$$" ] ; then rmdir "$TMP/bootstrap.$$" ; fi
606     if [ "$umountproc" = 1 ] ; then umount /proc ; fi
607     return 0
608 }
609
610 ##########
611 ## Main ##
612 ##########
613
614 ## absurdly bloated case statement to parse command line options.
615 if [ $# != 0 ] ; then
616     while true ; do
617         case "$1" in 
618             -V|--version)
619                 version
620                 exit 0
621                 ;;
622             -h|--help)
623                 usage
624                 exit 0
625                 ;;
626             --debug)
627                 DEBUG=1
628                 shift
629                 ;;
630             -v|--verbose)
631                 VERBOSE=1
632                 shift
633                 ;;
634             --force)
635                 # allow --force for now, boot-floppies 3.0.20 and
636                 # systemconfigurator use that instead of --format
637                 echo 1>&2 "$PRG: Warning: --force is now deprecated.  Use --for\mat."
638                 echo 1>&2 "Try \`$PRG --help' for more information."
639                 FORMAT=yes
640                 shift
641                 ;;
642             --format)
643                 FORMAT=yes
644                 shift
645                 ;;
646             --autoconf)
647                 autoconf=1
648                 shift
649                 ;;
650             -b|--boot)
651                 if [ -n "$2" ] ; then
652                     boot="$2"
653                     ARGBT=1
654                     shift 2
655                 else
656                     echo 1>&2 "$PRG: option requires an argument $1"
657                     echo 1>&2 "Try \`$PRG --help' for more information."
658                     exit 1
659                 fi
660                 ;;
661             -i|--install)
662                 if [ -n "$2" ] ; then
663                     install="$2"
664                     ARGBF=1
665                     shift 2
666                 else
667                     echo 1>&2 "$PRG: option requires an argument $1"
668                     echo 1>&2 "Try \`$PRG --help' for more information."
669                     exit 1
670                 fi
671                 ;;
672             -C|--config)
673                 if [ -n "$2" ] ; then
674                     CONF="$2"
675                     bootconf="$2"
676                     ERR=" Error in $CONF:"
677                     shift 2
678                 else
679                     echo 1>&2 "$PRG: option requires an argument $1"
680                     echo 1>&2 "Try \`$PRG --help' for more information."
681                     exit 1
682                 fi
683                 ;;
684             --efiboot)
685                 efiboot=1
686                 ARGNV=1
687                 shift
688                 ;;
689             --timeout)
690                 if [ -n "$2" ] ; then
691                     timeout="$2"
692                     bootconf=auto
693                     shift 2
694                 else
695                     echo 1>&2 "$PRG: option requires an argument $1"
696                     echo 1>&2 "Try \`$PRG --help' for more information."
697                     exit 1
698                 fi
699                 ;;
700             --image)
701                 if [ -n "$2" ] ; then
702                     image="$2"
703                     bootconf=auto
704                     shift 2
705                 else
706                     echo 1>&2 "$PRG: option requires an argument $1"
707                     echo 1>&2 "Try \`$PRG --help' for more information."
708                     exit 1
709                 fi
710                 ;;
711             --label)
712                 if [ -n "$2" ] ; then
713                     label="$2"
714                     bootconf=auto
715                     shift 2
716                 else
717                     echo 1>&2 "$PRG: option requires an argument $1"
718                     echo 1>&2 "Try \`$PRG --help' for more information."
719                     exit 1
720                 fi
721                 ;;
722             --root)
723                 if [ -n "$2" ] ; then
724                     root="$2"
725                     bootconf=auto
726                     shift 2
727                 else
728                     echo 1>&2 "$PRG: option requires an argument $1"
729                     echo 1>&2 "Try \`$PRG --help' for more information."
730                     exit 1
731                 fi
732                 ;;
733             "")
734                 break
735                 ;;
736             *)
737                 echo 1>&2 "$PRG: unrecognized option \`$1'"
738                 echo 1>&2 "Try \`$PRG --help' for more information."
739                 exit 1
740                 ;;
741         esac
742     done
743 fi
744
745 ## check that are root
746 if [ `id -u` != 0 ] ; then
747     echo 1>&2 "$PRG: requires root privileges, go away."
748     exit 1
749 fi
750
751 ## check that autoconf options are only specified with --autoconf
752 if [ "$bootconf" = "auto" ] && [ "$autoconf" = "0" ] ; then
753     echo 1>&2 "$PRG: Auto-config options specified without --autoconf."
754     exit 1;
755 fi
756
757 ## check that specified config file exists, unless we are to generate it,
758 ## which case we assume all options are done on the command line.
759 if [ "$autoconf" = "0" ] ; then
760     confexist || exit 1
761 fi
762
763 ## /proc is needed to parse /proc/partitions, etc.
764 if [ ! -f /proc/uptime ]; then
765     [ "$VERBOSE" = 1 ] && echo "$PRG: Mounting /proc..."
766     mount -t proc proc /proc 2> /dev/null
767     if [ $? != 0 ]; then
768         echo 1>&2 "$PRG: Failed to mount /proc, aborting."
769         exit 1
770     fi
771     umountproc=1
772 fi
773
774 # We need vfat support, so make sure it is loaded
775 modprobe vfat >/dev/null 2>&1
776
777 ## elilo.conf autogeneration. MUST have secure mktemp to
778 ## avoid race conditions. Debian's mktemp qualifies.
779 if [ "$autoconf" = "1" ] ; then
780     TMPCONF=`mktemp -q "$TMP/$PRG.XXXXXX"`
781     if [ $? != 0 ] ; then
782         echo 1>&2 "$PRG: Could not create temporary file, aborting."
783         exit 1
784     fi
785     mkconf
786     if [ $? != 0 ] ; then
787         echo 1>&2 "$PRG: An error occured generating elilo.conf, aborting."
788         exit 1
789     fi
790
791     bootconf="$TMPCONF"
792 fi
793
794 ## Checks if each option was defined on the command line, and if so
795 ## don't read it from the configuration file. this avoids
796 ## configuration options from being set null, as well as command line
797 ## options from being clobbered.
798 [ "$ARGBT" != 1 ] && [ $(parseconf ck boot) = 0 ] && boot=`parseconf str boot`
799
800 ## ffs!! rtfm! foad!
801 if [ "$boot" = unconfigured ] ; then
802     echo 1>&2 "$PRG: You must specify the device for the bootstrap partition. (ie: -b /dev/hdaX)"
803     echo 1>&2 "$PRG: Try \`$PRG --help' for more information."
804     exit 1
805 fi
806
807 ## validate configuration for sanity.
808 checkconf || exit 1
809
810 if [ "$FORMAT" = "yes" ]; then
811     mkefifs || exit 1
812 fi
813
814 [ "$VERBOSE" = 1 ] && echo "$PRG: Checking filesystem on $boot..."
815 dosfsck $boot > /dev/null
816 if [ $? != 0 ]; then
817     echo 1>&2 "$PRG: Filesystem on $boot is corrupt, please fix that and rerun $PRG."
818     exit 1
819 fi
820
821 mnt || exit 1
822 chkspace || exit 1
823 copyfiles || exit 1
824
825 umount $TARGET
826 if [ $? != 0 ]; then
827     echo 1>&2 "$PRG: Failed to unmount $boot"
828     exit 1
829 fi
830 TARGET=
831
832 [ "$VERBOSE" = 1 ] && echo "$PRG: Installation complete."
833
834 exit 0