Add externs to avoid multiple definitions, and then add missing definitions.
[rrq/maintain_lilo.git] / mkrescue
1 #!/bin/bash
2 #
3 #       mkrescue - create a boot floppy or cd image with the current kernel
4 #
5 #       Copyright 2001-2005 John Coffman
6 #       Copyright 2010-2011 Joachim Wiedorn <ad_debian at joonet.de>
7 #       
8 #       This program is free software; you can redistribute it and/or modify
9 #       it under the terms of the GNU General Public License as published by
10 #       the Free Software Foundation; either version 2 of the License, or
11 #       (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., 51 Franklin Street, Fifth Floor, Boston,
21 #       MA 02110-1301, USA.
22
23 debug=false
24 #debug=true
25
26 # set the version number on this command
27 version=3.8
28
29 # set the version of LILO required to run
30 major=22
31 minor=8
32 revision=0
33
34 log=$(pwd)/mkrescue.log
35 clog=$(pwd)/mkrescue.conf.log
36
37
38 usage () {
39     cat <<EOF
40
41 usage:  `basename $0` [--help]
42         `basename $0` [--version]
43         `basename $0` [--device <device>] [--fast] [--fs ext2|msdos|minix]
44             [--image <label>] [--install text|menu] [--keymap <keymap.ktl>] 
45             [--initrd <file> --kernel <file>] [--append <string>]
46             [--root <device>] [--nocompact] [--noformat]
47             [--iso] [--size 1440|1200|2880|HD]
48
49   --device   is the floppy drive; e.g.,  /dev/fd0
50   --fast     specifies creation using a loopback device, which may be faster
51   --fs       is the filesystem to make on the device; e.g.,  ext2
52   --help     prints this helpfile
53   --iso      create a bootable ISO image to burn to a CD-R or CD-RW
54   --keymap   is the keyboard translation table; default to same as lilo.conf
55   --noformat  bypasses creation of a new filesystem on device
56   --nocompact  omits lilo map file compaction
57   --size     is assumed to be 1440 (1.44M), unless 1200 or 2880 is specified
58              HD may be specified for ISO images
59   --image    specifies the label of the kernel/initrd if not the default
60   --install  'text' is the default for floppies, 'menu' for ISO images
61   --initrd   and --kernel  are the initial ramdisk & kernel files
62   --append   is a string used to specify kernel options
63   --root     is the root filesystem for the boot floppy; e.g., current
64   --version  prints the version number of `basename $0`
65   --debug    provide verbose output and pausing after defined steps
66
67 Used without any arguments, `basename $0` will use the default kernel in
68 /etc/lilo.conf, the companion initrd (if any), and the specified root
69 filesystem to make a bootable rescue floppy.
70
71 EOF
72     exit $1
73 }
74
75 if [ $debug != false ]; then
76         lilo=$(pwd)/lilo
77         config=$(pwd)/lilo.conf
78 else
79         lilo=/sbin/lilo
80         config=/etc/lilo.conf
81 fi
82
83 if [ ! -r "$config" ] ; then
84        echo "$0: Cannot read the configuration file $config (are you root?)"
85        exit 1
86 fi
87
88
89 compact=-c
90 device=/dev/fd0
91 fs=ext2
92 tmpbase="`mktemp -dt $(basename $0).XXXXXXXXXX`" || {
93     echo "Could not create temporary directory."; exit 1
94 }
95 mount="$tmpbase/mkrescue-flp"
96 mfile="$tmpbase/mkrescue-emu"
97 mtemp="$tmpbase/mkrescue-tmp"
98 mkdir "$mount"
99 touch "$mfile" "$mtemp"
100
101 loopback=loop0
102 looppart=loop1
103 install=text
104 isoimage=no
105 format=yes
106 image=
107 root=
108 bios=0x00
109 fast=slow
110 size=0
111 heads=2
112 sectors=18
113 cylinders=80
114 hdsize=16384
115 bootcmd=
116 append=
117 initrd=
118 boot=/boot
119 diag=no
120 master=
121
122 VERSION=$($lilo -V | awk '{print $3}' | sed -e "s/[^a-zA-Z0-9.]//g")
123
124 NVERSION=$(echo $VERSION | sed "s/\\./ /g")
125
126 DASH=$(echo $VERSION | sed "/-/s/.*-//" )
127 if [ "$DASH" = "$VERSION" ]; then
128         DASH=0
129 else
130         NVERSION=$(echo $NVERSION | sed "s/-.*//")
131 fi
132 MAJOR=$(echo $NVERSION | sed "s/ .*//")
133 MINOR=$(echo $NVERSION | sed -e "s/$MAJOR //" -e "s/ .*//" )
134 if [ "$MINOR" = "$NVERSION" ]; then
135         MINOR=0
136 fi
137 REVISION=$(echo $NVERSION | sed "s/$MAJOR $MINOR //")
138 if [ "$REVISION" = "$NVERSION" ]; then
139         REVISION=0
140 fi
141 REVISION=$(echo $REVISION | sed "s/ .*//")
142 if [ "$MINOR" -gt 49 ]; then MINOR=$(expr $MINOR % 10); fi
143
144 if [ $debug = true ]; then
145 echo ""
146 echo VERSION $VERSION
147 echo ""
148 echo MAJOR $MAJOR
149 echo MINOR $MINOR
150 echo REVISION $REVISION
151 echo DASH $DASH
152 echo ""
153 fi
154
155 #if [ "$MAJOR" -lt "$major" \
156 #       -o "$MINOR" -lt "$minor" \
157 #               -o $REVISION -lt "$revision" ]
158 skip=false
159 if [ "$REVISION" -lt "$revision" ]
160 then
161 skip=true
162 #echo $REVISION lt $revision
163 fi
164 if [ "$MINOR" -gt "$minor" ]
165 then
166 skip=false
167 #echo $MINOR gt $minor
168 fi
169 if [ "$MAJOR" -gt "$major" ]
170 then
171 skip=false
172 #echo $MAJOR gt $major
173 fi
174 if [ "$skip" = "true" ]
175 then
176     echo `basename $0` version $version
177     echo "LILO version $major.$minor.$revision (or newer) is required."
178     exit 0
179 fi
180
181 umount $mount 2>/dev/null
182 rm -rf $mount/*
183 > $mfile
184
185 master=`mount | grep " / " | cut -d " " -f 1`
186 master=`echo $master | sed "s/part[0-9]*$/disc/"`
187 master=`echo $master | sed "s/[0-9]*$//"`
188 if [ ! -b $master ]; then master=`echo $master | sed "s/p$//"`; fi
189 if [ ! -b $master ]; then master=""  ; fi
190
191
192 while [ $# -gt 0 ]; do
193     case $1 in
194         --append)
195             shift
196             append=$1
197             ;;
198         --debug)
199             debug=true
200             ;;
201         --device)
202             shift
203             device=$1
204             ;;
205         --fast)
206             fast=fast
207             ;;
208         --fs)
209             shift
210             fs=$1
211             ;;
212         -h)
213             usage 0
214             ;;
215         --help)
216             usage 0
217             ;;
218         --image)
219             shift
220             image=$1
221             ;;
222         --initrd)
223             shift
224             initrd=$1
225             ;;
226         --install)
227             shift
228             install=$1
229             ;;
230         --iso)
231             isoimage=yes
232             ;;
233         --kernel)
234             shift
235             kernel=$1
236             ;;
237         --keymap)
238             shift
239             keymap=$1
240             ;;
241         --nocompact)
242             compact=
243             ;;
244         --noformat)
245             format=no
246             ;;
247         --root)
248             shift
249             root=$1
250             ;;
251         --size)
252             shift
253             size=$1
254             ;;
255         --version)
256             echo `basename $0` version $version
257             exit 0
258             ;;
259         *)
260             echo "unrecognized argument: " $1
261             usage 1
262             ;;
263     esac
264
265     shift
266 done
267
268 if [ -z "$image" ]; then
269 #       image=`cat /proc/cmdline | sed "s/.*BOOT_IMAGE=//" | sed "s/ .*//"`
270         image=`$lilo -C $config -v0 -w -I " " D`
271 fi
272
273 if [ -z $kernel ]; then
274         kernel=`$lilo -C $config -v0 -w -I "$image" i`
275         if [ "$kernel" = "" ]; then exit 1;
276         elif [ $debug = "true" ]; then echo kernel = "$kernel";
277         fi
278 fi
279
280 if [ -z $root ]; then
281         root=`$lilo -C $config -v0 -w -I "$image" R`
282         if [ "$root" = "No root specified" ]; then
283                 root=`grep </etc/fstab -v "^[ \t]*#" |
284                         grep "[[:space:]]/[[:space:]]" | \
285                                 sed -e "s/^[ \t]*//" -e "s/[ \t].*//"`
286                 if [ -z $root ]; then
287                         root=`mount | grep " on / type" | sed "s/ .*//"`
288                 fi
289                 if [ -z $root ]; then
290                         echo "Cannot find mounted root partition"
291                         echo "Using current root"
292                         root=current
293                 fi
294         fi
295         if [ $debug = true ]; then echo root = "$root";
296         fi
297 fi
298
299 if [ -z $initrd ]; then
300         initrd=`$lilo -C $config -v0 -w -I "$image" r`
301         if [ "$initrd" = "" ]; then exit 1;
302         elif [ $debug = "true" ]; then echo initrd = "$initrd";
303         fi
304 fi
305 if [ "$initrd" = "No initial ramdisk specified" ]; then initrd= ; fi
306
307 if [ -z $append ]; then
308         append=`$lilo -C $config -v0 -w -I "$image" a`
309         if [ "$append" = "" ]; then exit 1;
310         elif [ $debug = "true" ]; then echo append = \"$append\";
311         fi
312 fi
313 if [ "$append" = "No append= was specified" ]; then append= ; fi
314
315 if [ -z $keymap ]; then
316         keymap=`$lilo -C $config -v0 -w -I "$image" k`
317         if [ "$keymap" = "" ]; then exit 1;
318         elif [ $debug = "true" ]; then echo keymap = "$keymap";
319         fi
320 fi
321
322 if [ $isoimage = yes ]; then
323     fast=fast
324     if [ $size = 0 ]; then
325         size=$hdsize
326     elif [ $size = HD -o $size = hd ]; then
327         size=$hdsize
328     fi
329     if [ $device = "/dev/fd0" ]; then
330         device=rescue.iso
331     fi
332 else
333         umount $device 2>/dev/null 1>/dev/null
334 fi
335
336 if [ $size = 0 ]; then
337     size=1440
338 fi
339
340 if [ $size = 1200 ]; then
341     sectors=15
342 elif [ $size = 1440 ]; then
343     sectors=18
344 elif [ $size = 2880 ]; then
345     sectors=36
346     install=menu
347     if [ -f $boot/diag1.img -a -f $boot/diag2.img ]; then
348         diag=yes
349     fi
350 elif [ $size = $hdsize ]; then
351     sectors=32
352     heads=8
353     cylinders=$(($size/$sectors/$heads*2))
354     if [ $size != $(($sectors*$heads*$cylinders/2)) ]; then
355         echo Internal error in HDsize
356         exit 1
357     fi
358     install=menu
359     if [ -f $boot/diag1.img -a -f $boot/diag2.img ]; then
360         diag=yes
361     fi
362 elif [ $size = HD -o $size = hd ]; then
363     echo "--size $size  may only be used with the  --iso  option."
364     exit 1
365 else
366     echo "--size must be 1200 or 1440; --size 1440 assumed."
367     sectors=18
368     size=1440
369 fi
370
371 if [ $fs != msdos -a $fs != ext2 -a $fs != minix ]; then
372     echo "illegal option:  --fs" $fs
373     echo "   must be either  msdos  or  ext2  or  minix"
374     exit 1
375 fi
376
377 if [ $fs = msdos ]; then
378         mountconfig=$mount/lilo.cnf
379 else
380         mountconfig=$mount/lilo.conf
381 fi
382
383 if [ $debug = "true" ]; then
384         umount $mfile
385
386         echo ""
387
388         echo lilo = $lilo
389         echo device = $device
390         echo image = $image
391         echo kernel = $kernel
392         echo initrd = $initrd
393         echo append = \"$append\"
394         echo install = $install
395         echo format = $format
396         echo fs = $fs
397         echo size = $size
398         echo root = $root
399         echo compact = $compact
400         echo keymap = $keymap
401         echo isoimage = $isoimage
402         echo master = $master
403         echo ""
404         echo pause after parameter display
405         read aline
406 fi
407
408 if [ ! -f $kernel ]; then
409         echo "Kernel file " $kernel " does not exist"
410         exit 1
411 fi
412
413 if [ ! -z $initrd ]; then
414         if [ ! -f $initrd ]; then
415                 echo "Initial ramdisk file " $initrd " does not exist"
416                 exit 1
417         fi
418 fi
419
420 if [ $isoimage != yes ]; then
421        # Calculate size
422         if [ -x /usr/bin/du ]; then
423                 totalsize=`/usr/bin/du -Dc $kernel $initrd $keymap |tail -1 | awk '{ print $1 }'`
424                 if [ "$totalsize" -gt "$size" ] ; then
425                         echo "Sorry, the ramdisk, kernel and keymap don't fit in the floppy disk."
426                         exit 1
427                 fi
428         fi
429         echo ""
430         echo "Insert a blank floppy into $device"
431         echo "All information on this floppy will be destroyed"
432         echo "Press [Enter] to proceed, ^C to abort"
433         read aline
434 fi
435
436 if [ "$fast" = fast ]; then
437
438         dd bs=1024 count=$size of=$mfile if=/dev/zero
439         bsize=$size
440         mpart=$mfile
441         if [ $size = $hdsize ]; then
442             bios=0x80
443             bsize=$(($size-$sectors))
444             cat > $mtemp <<EOF
445 n
446 p
447 1
448
449
450 a
451 1
452 w
453 EOF
454             echo Partitioning HD "file   (this will take a minute)"
455             fdisk -b 512 -S $sectors -H $heads -C $cylinders \
456                 $mfile < $mtemp > /dev/null 2> /dev/null
457             rm -f $mtemp
458             echo bsize = $bsize
459 #read aline
460             losetup -d /dev/$loopback 2>/dev/null
461             losetup -d /dev/$looppart 2>/dev/null
462             losetup /dev/$loopback $mfile
463             losetup -o $(($sectors*512)) /dev/$looppart $mfile
464             mpart=/dev/$looppart
465         fi
466         echo Making filesystem
467         if [ "$fs" = ext2 ]; then
468                 echo y | mkfs.$fs -N 24 -b 1024 $mpart $bsize
469         else
470                 echo y | mkfs.$fs $mpart
471         fi
472         echo Mounting filesystem
473 #read aline
474         if [ $size != $hdsize ]; then
475             mount -t $fs -o rw,loop $mfile $mount
476             loopback=`mount | grep $mfile | sed -e "sX.*loop=/dev/XX" -e "s/).*//"`
477         else
478             mount -t $fs -o rw $mpart $mount
479         fi
480         if [ $debug = true ]; then
481                 mount
482         fi
483         disk="/dev/$loopback"
484         if [ $debug = true ]; then
485                 echo "disk=$disk"
486         fi
487
488 else
489
490         if [ "$format" = "yes" ]; then
491                 echo Formatting $device with $fs filesystem...
492                 dd of=$device if=/dev/zero bs=512 count=1
493                 if [ "$fs" = ext2 ]; then
494                         mkfs -t $fs -N 24 -b 1024 $device 1>/dev/null 2>/dev/null
495                 else
496                         mkfs -t $fs $device 1>/dev/null 2>/dev/null
497                 fi
498                 echo done.
499                 echo ""
500         fi
501
502         rm -rf $mount/*
503         mount -t $fs -o rw $device $mount
504
505         rm -rf $mount/*
506         disk=$device
507
508 fi
509
510 cat > $mountconfig <<EOF
511 #  Begin mkrescue $version configuration file
512 install=$install
513 boot=$device
514 map=map
515 backup=/dev/null
516 message=message
517 prompt
518 timeout=150
519 nowarn
520 geometric
521 disk=$disk bios=$bios
522   sectors=$sectors heads=$heads cylinders=$cylinders
523 EOF
524 if [ $size = $hdsize ]; then
525         echo "  max-partitions=7" >>$mountconfig
526         echo "  partition=/dev/$looppart  start=$sectors" >>$mountconfig
527         echo static-bios-codes >>$mountconfig
528         bios=0x81
529 else
530         bios=0x80
531 fi
532
533 if [ "$master" != "" -a $isoimage = yes ]; then
534         echo "disk=$master" >>$mountconfig
535         echo "  bios=$bios" >>$mountconfig
536 elif [ "$master" != "" -a $debug = true ]; then
537         echo "disk=$master" >>$mountconfig
538         echo "  bios=$bios" >>$mountconfig
539 fi
540
541 if [ $keymap != us.ktl ]; then 
542         echo "keytable=lang.ktl" >>$mountconfig
543 fi
544
545 if [ $isoimage = yes ]; then 
546         echo "el-torito-bootable-CD" >>$mountconfig
547 fi
548
549 echo " " >>$mountconfig
550 echo "image=linux" >>$mountconfig
551
552 if [ ! -z $initrd ]; then
553         echo "  initrd=initrd" >>$mountconfig
554 fi
555
556 if [ ! -z "$append" ]; then
557         echo "  append=\"$append\"" >>$mountconfig
558 fi
559
560 cat >> $mountconfig <<EOF
561   root="$root"
562   read-only
563 EOF
564
565 if [ "$master" != "" -a $isoimage = yes ]; then
566 cat >> $mountconfig <<EOF
567 other=$master
568   unsafe
569   label=hard_disk
570 EOF
571 fi
572
573 if [ "$diag" = yes ]; then
574 cp -pv $boot/diag1.img $mount
575 cp -pv $boot/diag2.img $mount
576 cat >> $mountconfig <<EOF
577 image=diag1.img
578   label=diagnostic_1
579 image=diag2.img
580   label=diagnostic_2
581 EOF
582 fi
583 echo >>$mountconfig "#  End of mkrescue-generated configuration file"
584
585 if [ $isoimage = yes ]; then
586         comment="El-Torito bootable-CD will boot at end of timeout"
587 else
588         comment="floppy will boot in 15 seconds"
589 fi
590
591 rm -rf $mount/lost+found
592 cat > $mount/message <<EOF
593
594 MKRESCUE version $version $comment
595 Use  "boot: linux <options>"  to enter kernel options
596 The root device is currently configured as  root="$root"
597
598 EOF
599 echo `uname --sysname` `uname --release` > $mount/$(uname --release)
600
601 sync
602
603 if [ $debug = true ]; then
604         echo root=\"$root\"
605         echo ""
606         echo "pause after writing lilo.conf & message ..."
607         read aline
608 fi
609
610 echo "Copying files..."
611 if [ $keymap != us.ktl ]; then 
612         cp -pv $keymap $mount/lang.ktl
613 fi
614
615 if [ ! -z $initrd ]; then
616         cp -pv $initrd $mount/initrd
617 fi
618
619 cp -pv $kernel $mount/linux
620 sync
621
622 echo "done."
623 echo ""
624
625
626
627 pushd $mount >/dev/null 2>/dev/null
628 if [ "$fast" = fast ]; then
629         bootcmd="-b /dev/$loopback"
630 fi
631
632 echo Running $lilo ...
633 if [ $debug = true ]; then
634
635 cp -pvf $mountconfig $clog
636 if [ -z $log ]; then
637  echo   $lilo -w+ -C $mountconfig $compact $bootcmd -v5
638         $lilo -w+ -C $mountconfig $compact $bootcmd -v5 || fast=error
639 else
640  echo   $lilo -w+ -C $mountconfig $compact $bootcmd -v5 ">$log"
641         $lilo -w+ -C $mountconfig $compact $bootcmd -v5 >$log || fast=error
642 fi
643
644 else
645         $lilo -C $mountconfig $compact $bootcmd || fast=error
646 fi
647 popd >/dev/null 2>/dev/null
648 if [ "$fast" = error ]; then
649         echo -n `$lilo -V`
650         echo " failure."
651 else
652         echo done.
653 fi
654 echo ""
655
656 umount $mount
657
658 if [ $fast = error ]; then
659         exit 1
660 fi
661
662 if [ $isoimage = yes ]; then
663         echo START MakeISOFS:
664         echo
665         out=$device
666         opt=
667         if [ $size = $hdsize ]; then
668             losetup -d /dev/$looppart
669             losetup -d /dev/$loopback
670             opt=-hard-disk-boot
671         fi
672         mv $mfile $mount/boot.bin
673         genisoimage $opt -J -R -T \
674                 -V LILO_BOOT -A "Linux Boot CD created by LILO mkrescue" \
675                 -b boot.bin -c boot.cat -o $out $mount
676         cat <<EOF
677
678 END MakeISOFS:  output is in  '$device'
679
680
681 The bootable CD can be burned with the 'cdrecord' or 'wodim' utility
682 using a command of the form:
683
684         cdrecord [<options>] [dev=<device>] $device
685         wodim [<options>] [dev=<device>] $device
686
687 EOF
688 elif [ "$fast" = fast ]; then
689         if [ $debug = true ]; then
690                 echo Pause before transfering to $device
691                 read aline
692         fi
693         dd if=$mfile of=$device bs=1024
694 fi
695
696 echo "All done."
697 echo ""
698 exit 0
699