Ticket #103: update-grub

File update-grub, 30.6 KB (added by (none), 17 years ago)
Line 
1#!/bin/sh
2#
3# Insert a list of installed kernels in a grub menu.lst file
4# Copyright 2001 Wichert Akkerman <wichert@linux.com>
5#
6# This file is free software; you can redistribute it and/or modify it
7# under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14# General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19#
20# Contributors:
21# Jason Thomas <jason@debian.org>
22# David B.Harris <dbarclay10@yahoo.ca>
23# Marc Haber <mh@zugschlus.de>
24# Crispin Flowerday <crispin@zeus.com>
25
26# Abort on errors
27set -e
28
29host_os=`uname -s | tr '[A-Z]' '[a-z]'`
30
31abort() {
32 message=$@
33
34 echo >&2
35 printf '%s\n' "$message" >&2
36 echo >&2
37 exit 1
38}
39
40find_grub_dir ()
41{
42 echo -n "Searching for GRUB installation directory ... " >&2
43
44 for d in $grub_dirs ; do
45 if [ -d "$d" ] ; then
46 grub_dir="$d"
47 break
48 fi
49 done
50
51 if [ -z "$grub_dir" ] ; then
52 abort "No GRUB directory found.
53 To create a template run 'mkdir /boot/grub' first.
54 To install grub, install it manually or try the 'grub-install' command.
55 ### Warning, grub-install is used to change your MBR. ###"
56 else
57 echo "found: $grub_dir" >&2
58 fi
59
60 echo $grub_dir
61}
62
63find_device ()
64{
65 mount_point=$1
66
67 # Autodetect current root device
68 device=
69 if [ -f /etc/fstab ] ; then
70 while read DEV MNT FOO; do
71 if `echo "$DEV" | grep -q "^#"`; then
72 continue
73 fi
74 if [ "$MNT" = "$mount_point" ]; then
75 device="$DEV";
76 fi
77 done < /etc/fstab
78 fi
79
80 if [ -n "$device" ] ; then
81 case "$device" in
82 LABEL=* | UUID=*)
83 device=`readlink -f "$(findfs $device)"`
84 ;;
85 *)
86 device=`readlink -f "$device"`
87 ;;
88 esac
89 fi
90
91 echo $device
92}
93
94find_root_device ()
95{
96 device=$(find_device "/")
97
98 if [ -z "$device" ]; then
99 echo "Cannot determine root device. Assuming /dev/hda1" >&2
100 echo "This error is probably caused by an invalid /etc/fstab" >&2
101 device=/dev/hda1
102 fi
103
104 echo $device
105}
106
107# Usage: convert_kernel26 os_device
108# Convert system path to the kernel26 notation
109# I.e. /dev/ida/c0d0p2 -> /dev/ida!c0d0p2
110convert_kernel26 ()
111{
112 case "$1" in
113 /dev/rd/*)
114 echo "$1" | sed 's%^\(/dev/[^/]*\)/\(.*\)%\1!\2%'
115 ;;
116 *)
117 echo "$1"
118 ;;
119 esac
120}
121
122# Usage: convert_raid1 os_device
123# Checks if os_device is a software raid1.
124# If so, converts to first physical device in array.
125convert_raid1 ()
126{
127 case $1 in
128 /dev/md[0-9])
129 : ;; # Continue
130 *)
131 return 1 ;;
132 esac
133
134 [ -x /sbin/mdadm ] || return 1
135
136 # Check that the raid device is raid1
137 raidlevel=$(mdadm -D -b $1 | grep "^ARRAY" | \
138 sed "s/^.*level=//" | cut -d" " -f1)
139 [ "$raidlevel" = "raid1" ] || return 1
140
141 # Take only the first device that makes up the raid
142 raiddev=$(mdadm -D -b $1 | grep -A1 "Number" | grep "dev" | \
143 sed "s/^.*\(\/dev\/.*\)$/\1/")
144 [ -n "$raiddev" ] || return 1
145
146 echo $raiddev
147 return 0
148}
149
150# Usage: convert os_device
151# Convert an OS device to the corresponding GRUB drive.
152# This part is OS-specific.
153convert () {
154 # First, check if the device file exists.
155 if test -e "$1"; then
156 :
157 else
158 echo "$1: Not found or not a block device." 1>&2
159 exit 1
160 fi
161
162 host_os=`uname -s | tr '[[:upper:]]' '[[:lower:]]'`
163
164 # Break the device name into the disk part and the partition part.
165 case "$host_os" in
166 linux)
167 tmp_disk=`echo "$1" | sed -e 's%\([sh]d[[:lower:]]\)[0-9]*$%\1%' \
168 -e 's%\(fd[0-9]*\)$%\1%' \
169 -e 's%/part[0-9]*$%/disc%' \
170 -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
171 tmp_part=`echo "$1" | sed -e 's%.*/[sh]d[[:lower:]]\([0-9]*\)$%\1%' \
172 -e 's%.*/fd[0-9]*$%%' \
173 -e 's%.*/floppy/[0-9]*$%%' \
174 -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
175 -e 's%.*c[0-7]d[0-9]*p*%%'`
176 ;;
177 gnu)
178 tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
179 tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;;
180 freebsd|*/kfreebsd)
181 tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%\1%' \
182 | sed 's%r\{0,1\}\(da[0-9]*\).*$%\1%'`
183 tmp_part=`echo "$1" \
184 | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
185 | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
186 ;;
187 netbsd|*/knetbsd)
188 tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([sw]d[0-9]*\).*$%r\1d%' \
189 | sed 's%r\{0,1\}\(fd[0-9]*\).*$%r\1a%'`
190 tmp_part=`echo "$1" \
191 | sed "s%.*/r\{0,1\}[sw]d[0-9]\([abe-p]\)%\1%"`
192 ;;
193 *)
194 echo "update-grub does not support your OS yet." 1>&2
195 exit 1 ;;
196 esac
197
198 # Get the drive name.
199 tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \
200 | sed 's%.*\(([hf]d[0-9][a-z0-9,]*)\).*%\1%'`
201
202 # If not found, print an error message and exit.
203 if test "x$tmp_drive" = x; then
204 echo "$1 does not have any corresponding BIOS drive." 1>&2
205 exit 1
206 fi
207
208 if test "x$tmp_part" != x; then
209 # If a partition is specified, we need to translate it into the
210 # GRUB's syntax.
211 case "$host_os" in
212 linux)
213 echo "$tmp_drive" | sed "s%)$%,`expr $tmp_part - 1`)%" ;;
214 gnu)
215 if echo $tmp_part | grep "^s" >/dev/null; then
216 tmp_pc_slice=`echo $tmp_part \
217 | sed "s%s\([0-9]*\)[a-z]*$%\1%"`
218 tmp_drive=`echo "$tmp_drive" \
219 | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
220 fi
221 if echo $tmp_part | grep "[a-z]$" >/dev/null; then
222 tmp_bsd_partition=`echo "$tmp_part" \
223 | sed "s%[^a-z]*\([a-z]\)$%\1%"`
224 tmp_drive=`echo "$tmp_drive" \
225 | sed "s%)%,$tmp_bsd_partition)%"`
226 fi
227 echo "$tmp_drive" ;;
228 freebsd|*/kfreebsd)
229 if echo $tmp_part | grep "^s" >/dev/null; then
230 tmp_pc_slice=`echo $tmp_part \
231 | sed "s%s\([0-9]*\)[a-h]*$%\1%"`
232 tmp_drive=`echo "$tmp_drive" \
233 | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
234 fi
235 if echo $tmp_part | grep "[a-h]$" >/dev/null; then
236 tmp_bsd_partition=`echo "$tmp_part" \
237 | sed "s%s\{0,1\}[0-9]*\([a-h]\)$%\1%"`
238 tmp_drive=`echo "$tmp_drive" \
239 | sed "s%)%,$tmp_bsd_partition)%"`
240 fi
241 echo "$tmp_drive" ;;
242 netbsd|*/knetbsd)
243 if echo $tmp_part | grep "^[abe-p]$" >/dev/null; then
244 tmp_bsd_partition=`echo "$tmp_part" \
245 | sed "s%\([a-p]\)$%\1%"`
246 tmp_drive=`echo "$tmp_drive" \
247 | sed "s%)%,$tmp_bsd_partition)%"`
248 fi
249 echo "$tmp_drive" ;;
250 esac
251 else
252 # If no partition is specified, just print the drive name.
253 echo "$tmp_drive"
254 fi
255}
256
257# Usage: convert_default os_device
258# Convert an OS device to the corresponding GRUB drive.
259# Calls OS-specific convert, and returns a default of
260# (hd0,0) if anything goes wrong
261convert_default () {
262 # Check if device is software raid1 array
263 if tmp_dev=$(convert_raid1 $1 2>/dev/null) ; then
264 : # Use device returned by convert_raid1
265 else
266 tmp_dev=$1
267 fi
268
269 if tmp=$(convert $tmp_dev 2>/dev/null) ; then
270 echo $tmp
271 else
272 echo "(hd0,0)"
273 fi
274}
275
276is_removable () {
277 removabledevice="$(echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' -e 's%\(fd[0-9]*\)$%\1%' -e 's%/part[0-9]*$%/disc%' -e 's%\(c[0-7]d[0-9]*\).*$%\1%' -e 's%^/dev/%%g')"
278 if [ -e "/sys/block/$removabledevice/removable" ]; then
279 if [ "$(cat /sys/block/$removabledevice/removable)" != "0" ]; then
280 echo "/dev/$removabledevice"
281 return
282 fi
283 fi
284 echo ""
285}
286
287## Configuration Options
288# directory's to look for the grub installation and the menu file
289grub_dirs="/boot/grub /boot/boot/grub"
290
291# The grub installation directory
292grub_dir=$(find_grub_dir)
293
294# Full path to the menu.lst
295menu_file=$grub_dir/menu.lst
296
297# the device for the / filesystem
298root_device=$(find_root_device)
299root_device_2_6=$(convert_kernel26 "$root_device")
300
301# the device for the /boot filesystem
302boot_device=$(find_device "/boot")
303
304# Full path to the device.map
305device_map=$grub_dir/device.map
306
307# Default kernel options, overidden by the kopt statement in the menufile.
308kopt="root=$(awk '$2 == "/" {print $1}' /etc/fstab) ro"
309
310# Title
311title="Ubuntu"
312
313# should update-grub remember the default entry
314updatedefaultentry="false"
315
316# Drive(in GRUB terms) where the kernel is located. Overridden by the
317# kopt statement in menufile.
318# if we don't have a device.map then we can't use the convert function.
319check_removable=""
320if test -f "$device_map" ; then
321 if test -z "$boot_device" ; then
322 grub_root_device=$(convert_default "$root_device")
323 check_removable="$(is_removable "$root_device")"
324 else
325 grub_root_device=$(convert_default "$boot_device")
326 check_removable="$(is_removable "$boot_device")"
327 fi
328else
329 grub_root_device="(hd0,0)"
330fi
331
332# If the root/boot device is on a removable target, we need to override
333# the grub_root_device to (hd0,X). This is a requirement since the BIOS
334# will change device mapping dynamically if we switch boot device.
335
336if test -n "$check_removable" ; then
337 grub_root_device="$(echo "$grub_root_device" | sed -e 's/d.*,/d0,/g')"
338fi
339
340# should grub create the alternative boot options in the menu
341 alternative="true"
342
343# should grub lock the alternative boot options in the menu
344 lockalternative="false"
345
346# additional options to use with the default boot option, but not with the
347# alternatives
348 defoptions="quiet splash"
349
350# should grub lock the old kernels
351 lockold="false"
352
353# options to use with the alternative boot options
354 altoptions="(recovery mode) single"
355
356# controls howmany kernels are listed in the menu.lst,
357# this does not include the alternative kernels
358 howmany="all"
359
360# should grub create a memtest86 entry
361 memtest86="true"
362
363# stores the command line arguments
364 command_line_arguments=$1
365
366# does this version of grub support the quiet option?
367if [ -f ${grub_dir}/installed-version ] && dpkg --compare-versions `cat ${grub_dir}/installed-version` ge 0.97-11ubuntu4; then
368 supports_quiet=true
369else
370 supports_quiet=false
371fi
372
373# read user configuration
374if test -f "/etc/default/grub" ; then
375 . /etc/default/grub
376fi
377
378# Default options to use in a new menu.lst . This will only be used if menu.lst
379# doesn't already exist. Only edit the lines between the two "EOF"s. The others are
380# part of the script.
381newtemplate=$(tempfile)
382cat > "$newtemplate" <<EOF
383# menu.lst - See: grub(8), info grub, update-grub(8)
384# grub-install(8), grub-floppy(8),
385# grub-md5-crypt, /usr/share/doc/grub
386# and /usr/share/doc/grub-doc/.
387
388## default num
389# Set the default entry to the entry number NUM. Numbering starts from 0, and
390# the entry number 0 is the default if the command is not used.
391#
392# You can specify 'saved' instead of a number. In this case, the default entry
393# is the entry saved with the command 'savedefault'.
394# WARNING: If you are using dmraid do not change this entry to 'saved' or your
395# array will desync and will not let you boot your system.
396default 0
397
398## timeout sec
399# Set a timeout, in SEC seconds, before automatically booting the default entry
400# (normally the first entry defined).
401timeout 3
402
403## hiddenmenu
404# Hides the menu by default (press ESC to see the menu)
405hiddenmenu
406
407# Pretty colours
408#color cyan/blue white/blue
409
410## password ['--md5'] passwd
411# If used in the first section of a menu file, disable all interactive editing
412# control (menu entry editor and command-line) and entries protected by the
413# command 'lock'
414# e.g. password topsecret
415# password --md5 \$1\$gLhU0/\$aW78kHK1QfV3P2b2znUoe/
416# password topsecret
417
418#
419# examples
420#
421# title Windows 95/98/NT/2000
422# root (hd0,0)
423# makeactive
424# chainloader +1
425#
426# title Linux
427# root (hd0,1)
428# kernel /vmlinuz root=/dev/hda2 ro
429#
430
431#
432# Put static boot stanzas before and/or after AUTOMAGIC KERNEL LIST
433
434EOF
435## End Configuration Options
436
437
438# Make sure we use the standard sorting order
439LC_COLLATE=C
440# Magic markers we use
441start="### BEGIN AUTOMAGIC KERNELS LIST"
442end="### END DEBIAN AUTOMAGIC KERNELS LIST"
443
444startopt="## ## Start Default Options ##"
445endopt="## ## End Default Options ##"
446
447# Extract options from menu.lst
448ExtractMenuOpt()
449{
450 opt=$1
451
452 sed -ne "/^$start\$/,/^$end\$/ {
453 /^$startopt\$/,/^$endopt\$/ {
454 /^# $opt=/ {
455 s/^# $opt=\(.*\)\$/\1/
456 p
457 }
458 }
459 }" $menu
460}
461
462GetMenuOpts()
463{
464 opt=$1
465
466 sed -ne "/^$start\$/,/^$end\$/ {
467 /^$startopt\$/,/^$endopt\$/ {
468 /^# $opt=/ {
469 p
470 }
471 }
472 }" $menu
473}
474
475ExtractMenuOpts()
476{
477 opt=$1
478
479 GetMenuOpts $opt | sed "s/^# $opt=\(.*\)\$/\1=\"\2\"/"
480}
481
482GetMenuOpt()
483{
484 opt=$1
485 value=$2
486
487 tmp=$(ExtractMenuOpt "$opt")
488
489 [ -z "$tmp" ] || value="$tmp"
490
491 echo $value
492}
493
494# Compares two version strings A and B
495# Returns -1 if A<B
496# 0 if A==B
497# 1 if A>B
498# This compares version numbers of the form
499# 2.4.14.2 > 2.4.14
500# 2.4.14random = 2.4.14-random > 2.4.14-ac10 > 2.4.14 > 2.4.14-pre2 >
501# 2.4.14-pre1 > 2.4.13-ac99
502CompareVersions()
503{
504 #Changes the line something-x.y.z into somthing-x.y.z.q
505 #This is to ensure that kernels with a .q is treated as higher than the ones without
506 #First a space is put after the version number
507 v1=$(echo $1 | sed -e 's!^\(.*-\([0-9]\+\.\)\{2,3\}[0-9]\+\)\(.*\)!\1 \3!g')
508 v2=$(echo $2 | sed -e 's!^\(.*-\([0-9]\+\.\)\{2,3\}[0-9]\+\)\(.*\)!\1 \3!g')
509 #If the version number only has 3 digits then put in another .0
510 v1=$(echo $v1 | sed -e 's!^\(.*-\([0-9]\+\.\)\{2\}[0-9]\+\)\( .*\)!\1.0 \3!g')
511 v2=$(echo $v2 | sed -e 's!^\(.*-\([0-9]\+\.\)\{2\}[0-9]\+\)\( .*\)!\1.0 \3!g')
512
513 # Then split the version number and remove any '.' 's or dashes
514 v1=$(echo $v1 | sed -e 's![-\.]\+! !g' -e 's!\([0-9]\)\([[:alpha:]]\)!\1 \2!')
515 v2=$(echo $v2 | sed -e 's![-\.]\+! !g' -e 's!\([0-9]\)\([[:alpha:]]\)!\1 \2!')
516
517 # we weight different kernel suffixes here
518 # ac = 50
519 # pre = -50
520 # rc = -40
521 # test = -60
522 # others are given 99
523 v1=$(echo $v1 | sed -e 's! k7! 786 !g' -e 's! ac! 50 !g' -e 's! rc! -40 !g' -e 's! pre! -50 !g' -e 's! test! -60 !g' -e 's![^-0-9 ]\+!99!g')
524
525 v2=$(echo $v2 | sed -e 's! k7! 786 !g' -e 's! ac! 50 !g' -e 's! rc! -40 !g' -e 's! pre! -50 !g' -e 's! test! -60 !g' -e 's![^-0-9 ]\+!99!g')
526
527 result=0; v1finished=0; v2finished=0;
528 while [ $result -eq 0 ] && [ $v1finished -eq 0 ] && [ $v2finished -eq 0 ];
529 do
530 if [ "$v1" = "" ]; then
531 v1comp=0; v1finished=1
532 else
533 set -- $v1; v1comp=$1; shift; v1=$*
534 fi
535
536 if [ "$v2" = "" ]; then
537 v2comp=0; v2finished=1
538 else
539 set -- $v2; v2comp=$1; shift; v2=$*
540 fi
541
542 set +e
543 result=`expr $v1comp - $v2comp`
544 result=`expr substr $result 1 2`
545 set -e
546
547 if [ $result -gt 0 ]; then result=1
548 elif [ $result -lt 0 ]; then result=-1
549 fi
550 done
551
552 # finally return the result
553 echo $result
554}
555
556# looks in the directory specified for an initrd image with the version specified
557FindInitrdName()
558{
559 # strip trailing slashes
560 directory=$(echo $1 | sed -e 's#/*$##')
561 version=$2
562
563 # initrd
564 # initrd.img
565 # initrd-lvm
566 # .*.gz
567
568 initrdName=""
569 names="initrd initrd.img initrd-lvm"
570 compressed="gz"
571
572 for n in $names ; do
573 # make sure we haven't already found it
574 if [ -z "$initrdName" ] ; then
575 if [ -f "$directory/$n$version" ] ; then
576 initrdName="$n$version"
577 break
578 else
579 for c in $compressed ; do
580 if [ -f "$directory/$n$version.$c" ] ; then
581 initrdName="$n$version.$c"
582 break
583 fi
584 done
585 fi
586 else
587 break
588 fi
589 done
590
591 # return the result
592 echo $initrdName
593}
594
595get_kernel_opt()
596{
597 kernel_version=$1
598
599 version=$(echo $kernel_version | sed 's/^[^0-9]*//')
600 version=$(echo $version | sed 's/[-\+\.]/_/g')
601 if [ -n "$version" ] ; then
602 while [ -n "$version" ] ; do
603 currentOpt="$(eval "echo \${kopt_$version}")"
604 if [ -n "$currentOpt" ] ; then
605 break
606 fi
607
608 oldversion="$version"
609 version=$(echo $version | sed 's/_\?[^_]*$//')
610 if [ "$version" = "$oldversion" ] ; then
611 # Break infinite loop, if the version isn't what we expect
612 break
613 fi
614 done
615 fi
616
617 if [ -z "$currentOpt" ] ; then
618 currentOpt=$kopt
619 fi
620
621 echo $currentOpt
622}
623
624write_kernel_entry()
625{
626 kernel_version=$1
627 recovery_desc=$2
628 lock_alternative=$3
629 grub_root_device=$4
630 kernel=$5
631 kernel_options=$6
632 recovery_suffix=$7
633 initrd=$8
634 savedefault=$9
635
636 echo -n "title $title, " >> $buffer
637 # memtest86 is not strictly a kernel
638 if ! echo "$kernel_version" | grep -q ^memtest86; then
639 echo -n "kernel " >> $buffer
640 fi
641 echo -n "$kernel_version" >> $buffer
642 if [ -n "$recovery_desc" ]; then
643 echo -n " $recovery_desc" >> $buffer
644 fi
645 echo >> $buffer
646
647 # lock the alternative options
648 if test x"$lock_alternative" = x"true" ; then
649 echo "lock" >> $buffer
650 fi
651 # lock the old entries
652 if test x"$lockold" = x"true" ; then
653 echo "lock" >> $buffer
654 fi
655
656 echo "root $grub_root_device" >> $buffer
657 echo -n "kernel $kernel" >> $buffer
658 if [ -n "$kernel_options" ]; then
659 echo -n " $kernel_options" >> $buffer
660 fi
661 if [ -n "$recovery_desc" ]; then
662 echo -n " $recovery_suffix" >> $buffer
663 fi
664 echo >> $buffer
665
666 if [ -n "$initrd" ]; then
667 echo "initrd $initrd" >> $buffer
668 fi
669
670 if [ ! -n "$recovery_desc" -a x"$supports_quiet" = x"true" ]; then
671 echo "quiet" >> $buffer
672 fi
673
674 if test x"$savedefault" = x"true" ; then
675 echo "savedefault" >> $buffer
676 fi
677 echo "boot" >> $buffer
678 echo >> $buffer
679}
680
681convert_kopt_to_uuid()
682{
683 kopt=$1
684
685 root=$(echo "$kopt" | sed 's/.*root=//;s/ .*//')
686 case "$root" in
687 UUID=*|LABEL=*)
688 ;;
689 /dev/disk/*)
690 ;;
691 /dev/mapper/*)
692 ;;
693 /dev/evms/*)
694 ;;
695 /dev/md[0-9]*)
696 ;;
697 /dev/*)
698 if [ -L "$DEV" ] && readlink | grep -q "^/dev/mapper/"
699 then
700 :
701 elif [ -b "$root" ]; then
702 uuid=$(/sbin/vol_id -u "$root" || true)
703 if [ -n "$uuid" ]; then
704 kopt=$(echo "$kopt" | sed "s/\(.*root=\)[^ ]*/\1UUID=$uuid/")
705 fi
706 fi
707 ;;
708 esac
709
710 echo "$kopt"
711}
712
713
714echo -n "Testing for an existing GRUB menu.list file ... " >&2
715
716# Test if our menu file exists
717if [ -f "$menu_file" ] ; then
718 menu="$menu_file"
719 rm -f $newtemplate
720 unset newtemplate
721 echo "found: $menu_file" >&2
722 cp -f "$menu_file" "$menu_file~"
723else
724 # if not ask user if they want us to create one
725 menu="$menu_file"
726 echo >&2
727 echo >&2
728 echo -n "Could not find $menu_file file. " >&2
729 if [ "-y" = "$command_line_arguments" ] ; then
730 echo >&2
731 echo "Generating $menu_file" >&2
732 answer=y
733 else
734 echo -n "Would you like $menu_file generated for you? " >&2
735 echo -n "(y/N) " >&2
736 read answer
737 fi
738
739 case "$answer" in
740 y* | Y*)
741 cat "$newtemplate" > $menu_file
742 rm -f $newtemplate
743 unset newtemplate
744 ;;
745 *)
746 abort "Not creating $menu_file as you wish"
747 ;;
748 esac
749fi
750
751# Extract the kernel options to use
752kopt=$(GetMenuOpt "kopt" "$kopt")
753
754# Update the root device to mount-by-UUID
755kopt=$(convert_kopt_to_uuid "$kopt")
756
757# Set the kernel 2.6 option only for fresh install
758test -z "$(GetMenuOpt "kopt" "")" && kopt_2_6="root=$root_device_2_6 ro"
759
760# Extract options for specific kernels
761opts="$(ExtractMenuOpts "\(kopt_[[:alnum:]_]\+\)")"
762test -z "$opts" || eval "$opts"
763CustomKopts=$(GetMenuOpts "\(kopt_[[:alnum:]_]\+\)")
764
765# Extract the grub root
766grub_root_device=$(GetMenuOpt "groot" "$grub_root_device")
767
768# Extract the old recovery value
769alternative=$(GetMenuOpt "recovery" "$alternative")
770
771# Extract the alternative value
772alternative=$(GetMenuOpt "alternative" "$alternative")
773
774# Extract the lockalternative value
775lockalternative=$(GetMenuOpt "lockalternative" "$lockalternative")
776
777# Extract the additional default options
778# Check nonaltoptions too for compatibility with Ubuntu <= 5.10
779defoptions=$(GetMenuOpt "nonaltoptions" "$defoptions")
780defoptions=$(GetMenuOpt "defoptions" "$defoptions")
781
782# Extract the lockold value
783lockold=$(GetMenuOpt "lockold" "$lockold")
784
785# Extract the howmany value
786howmany=$(GetMenuOpt "howmany" "$howmany")
787
788# Extract the memtest86 value
789memtest86=$(GetMenuOpt "memtest86" "$memtest86")
790
791
792# Extract the updatedefaultentry option
793updatedefaultentry=$(GetMenuOpt "updatedefaultentry" "$updatedefaultentry")
794
795
796# Generate the menu options we want to insert
797buffer=$(tempfile)
798echo $start >> $buffer
799echo "## lines between the AUTOMAGIC KERNELS LIST markers will be modified" >> $buffer
800echo "## by the debian update-grub script except for the default options below" >> $buffer
801echo >> $buffer
802echo "## DO NOT UNCOMMENT THEM, Just edit them to your needs" >> $buffer
803echo >> $buffer
804echo "## ## Start Default Options ##" >> $buffer
805
806echo "## default kernel options" >> $buffer
807echo "## default kernel options for automagic boot options" >> $buffer
808echo "## If you want special options for specific kernels use kopt_x_y_z" >> $buffer
809echo "## where x.y.z is kernel version. Minor versions can be omitted." >> $buffer
810echo "## e.g. kopt=root=/dev/hda1 ro" >> $buffer
811echo "## kopt_2_6_8=root=/dev/hdc1 ro" >> $buffer
812echo "## kopt_2_6_8_2_686=root=/dev/hdc2 ro" >> $buffer
813echo "# kopt=$kopt" >> $buffer
814if [ -n "$CustomKopts" ] ; then
815 echo "$CustomKopts" >> $buffer
816elif [ -n "$kopt_2_6" ] && [ "$kopt" != "$kopt_2_6" ]; then
817 echo "# kopt_2_6=$kopt_2_6" >> $buffer
818fi
819echo >> $buffer
820
821echo "## default grub root device" >> $buffer
822echo "## e.g. groot=(hd0,0)" >> $buffer
823echo "# groot=$grub_root_device" >> $buffer
824echo >> $buffer
825
826echo "## should update-grub create alternative automagic boot options" >> $buffer
827echo "## e.g. alternative=true" >> $buffer
828echo "## alternative=false" >> $buffer
829echo "# alternative=$alternative" >> $buffer
830echo >> $buffer
831
832echo "## should update-grub lock alternative automagic boot options" >> $buffer
833echo "## e.g. lockalternative=true" >> $buffer
834echo "## lockalternative=false" >> $buffer
835echo "# lockalternative=$lockalternative" >> $buffer
836echo >> $buffer
837
838echo "## additional options to use with the default boot option, but not with the" >> $buffer
839echo "## alternatives" >> $buffer
840echo "## e.g. defoptions=vga=791 resume=/dev/hda5" >> $buffer
841echo "# defoptions=$defoptions" >> $buffer
842echo >> $buffer
843
844echo "## should update-grub lock old automagic boot options" >> $buffer
845echo "## e.g. lockold=false" >> $buffer
846echo "## lockold=true" >> $buffer
847echo "# lockold=$lockold" >> $buffer
848echo >> $buffer
849
850echo "## altoption boot targets option" >> $buffer
851echo "## multiple altoptions lines are allowed" >> $buffer
852echo "## e.g. altoptions=(extra menu suffix) extra boot options" >> $buffer
853echo "## altoptions=(recovery) single" >> $buffer
854
855if ! grep -q "^# altoptions" $menu ; then
856 echo "# altoptions=$altoptions" >> $buffer
857else
858 grep "^# altoptions" $menu >> $buffer
859fi
860echo >> $buffer
861
862echo "## controls how many kernels should be put into the menu.lst" >> $buffer
863echo "## only counts the first occurence of a kernel, not the" >> $buffer
864echo "## alternative kernel options" >> $buffer
865echo "## e.g. howmany=all" >> $buffer
866echo "## howmany=7" >> $buffer
867echo "# howmany=$howmany" >> $buffer
868echo >> $buffer
869
870
871echo "## should update-grub create memtest86 boot option" >> $buffer
872echo "## e.g. memtest86=true" >> $buffer
873echo "## memtest86=false" >> $buffer
874echo "# memtest86=$memtest86" >> $buffer
875echo >> $buffer
876
877echo "## should update-grub adjust the value of the default booted system" >> $buffer
878echo "## can be true or false" >> $buffer
879echo "# updatedefaultentry=$updatedefaultentry" >> $buffer
880echo >> $buffer
881
882echo "## ## End Default Options ##" >> $buffer
883echo >> $buffer
884
885echo -n "Searching for splash image ... " >&2
886current_splash=`grep '^splashimage=' ${grub_dir}/menu.lst || true`
887splashimage_path="splashimage=${grub_root_device}${grub_dir##${boot_device:+/boot}}/splash.xpm.gz"
888if [ `sed -e "/^$start/,/^$end/d" $grub_dir/menu.lst | grep -c '^splashimage='` != "0" ] ; then
889 #checks for splashscreen defined outside the autoupdated part
890 splashimage=$(grep '^splashimage=' ${grub_dir}/menu.lst)
891 echo "found: ${splashimage##*=}" >&2
892 echo >&2
893elif [ -f "${grub_dir}/splash.xpm.gz" ] && [ "$current_splash" = "" ]; then
894 echo "found: /boot/grub/splash.xpm.gz" >&2
895 echo "$splashimage_path" >> $buffer
896 echo >> $buffer
897elif [ -f "${grub_dir}/splash.xpm.gz" ] && [ "$current_splash" = "$splashimage_path" ]; then
898 echo "found: /boot/grub/splash.xpm.gz" >&2
899 echo "$splashimage_path" >> $buffer
900 echo >> $buffer
901elif [ "$current_splash" != "" ] && [ "$current_splash" != "$splashimage_path" ]; then
902 echo "found but preserving previous setting: $(grep '^splashimage=' ${grub_dir}/menu.lst)" >&2
903 echo "$current_splash" >> $buffer
904 echo >> $buffer
905else
906 echo "none found, skipping ..." >&2
907fi
908
909
910sortedKernels=""
911for kern in $(/bin/ls -1vr /boot | grep -v "dpkg-*" | grep "^vmlinuz-") ; do
912 # found a kernel
913 kern="/boot/$kern"
914 newerKernels=""
915 for i in $sortedKernels ; do
916 res=$(CompareVersions "$kern" "$i")
917 if [ "$kern" != "" ] && [ "$res" -gt 0 ] ; then
918 newerKernels="$newerKernels $kern $i"
919 kern=""
920 else
921 newerKernels="$newerKernels $i"
922 fi
923 done
924 if [ "$kern" != "" ] ; then
925 newerKernels="$newerKernels $kern"
926 fi
927 sortedKernels="$newerKernels"
928done
929
930if test -f "/boot/vmlinuz.old" ; then
931 sortedKernels="/boot/vmlinuz.old $sortedKernels"
932fi
933if test -f "/boot/vmlinuz" ; then
934 sortedKernels="/boot/vmlinuz $sortedKernels"
935fi
936
937# figure out where grub looks for the kernels at boot time
938kernel_dir=/boot
939if [ -n "$boot_device" ] ; then
940 kernel_dir=
941fi
942
943#Finding the value the default line
944use_grub_set_default="false"
945if test "$updatedefaultentry" = "true" ; then
946 defaultEntryNumber=$(sed -ne 's/^[[:blank:]]*default[[:blank:]]*\(.*\).*/\1/p' $menu)
947
948 if [ "$defaultEntryNumber" = "saved" ] ; then
949 defaultEntryNumber=$(sed 'q' "$grub_dir/default")
950 use_grub_set_default="true"
951 fi
952
953 if test -n "$defaultEntryNumber"; then
954 defaultEntryNumberPlusOne=$(expr $defaultEntryNumber \+ 1);
955 defaultEntry=$(grep "^[[:blank:]]*title" $menu | sed -ne "${defaultEntryNumberPlusOne}p" | sed -ne ";s/^[[:blank:]]*title[[:blank:]]*//p")
956 defaultEntry=$(echo $defaultEntry | sed -e "s/[[:blank:]]*$//") # don't trust trailing blanks
957 else
958 notChangeDefault="yes"
959 fi
960else
961 notChangeDefault="yes"
962fi
963
964## heres where we start writing out the kernel entries
965counter=0
966for kern in $sortedKernels ; do
967 counter=$(($counter + 1))
968 if test ! x"$howmany" = x"all" ; then
969 if [ $counter -gt $howmany ] ; then
970 break
971 fi
972 fi
973 kernelName=$(basename $kern)
974 kernelVersion=$(echo $kernelName | sed -e 's/vmlinuz//')
975 initrdName=$(FindInitrdName "/boot" "$kernelVersion")
976 initrd=""
977
978 kernel=$kernel_dir/$kernelName
979 if [ -n "$initrdName" ] ; then
980 initrd=$kernel_dir/$initrdName
981 fi
982
983 echo "Found kernel: $kernel" >&2
984
985 if [ "$kernelName" = "vmlinuz" ]; then
986 if [ -L "/boot/$kernelName" ]; then
987 kernelVersion=`readlink -f "/boot/$kernelName"`
988 kernelVersion=$(echo $kernelVersion | sed -e 's/.*vmlinuz-//')
989 kernelVersion="$kernelVersion Default"
990 else
991 kernelVersion="Default"
992 fi
993 fi
994 if [ "$kernelName" = "vmlinuz.old" ]; then
995 if [ -L "/boot/$kernelName" ]; then
996 kernelVersion=`readlink -f "/boot/$kernelName"`
997 kernelVersion=$(echo $kernelVersion | sed -e 's/.*vmlinuz-//')
998 kernelVersion="$kernelVersion Previous"
999 else
1000 kernelVersion="Previous"
1001 fi
1002 fi
1003 kernelVersion=$(echo $kernelVersion | sed -e 's/^-//')
1004
1005 currentOpt=$(get_kernel_opt $kernelVersion)
1006
1007 do_lockold=$lockold
1008 # do not lockold for the first entry
1009 [ $counter -eq 1 ] && do_lockold=false
1010
1011 write_kernel_entry "$kernelVersion" "" "" "$grub_root_device" "$kernel" \
1012 "$currentOpt $defoptions" "" "$initrd" "true" "$do_lockold"
1013
1014 # insert the alternative boot options
1015 if test ! x"$alternative" = x"false" ; then
1016 # for each altoptions line do this stuff
1017 sed -ne 's/# altoptions=\(.*\)/\1/p' $buffer | while read line; do
1018 descr=$(echo $line | sed -ne 's/\(([^)]*)\)[[:space:]]\(.*\)/\1/p')
1019 suffix=$(echo $line | sed -ne 's/\(([^)]*)\)[[:space:]]\(.*\)/\2/p')
1020
1021 test x"$lockalternative" = x"true" && do_lockold=false
1022 write_kernel_entry "$kernelVersion" "$descr" "$lockalternative" \
1023 "$grub_root_device" "$kernel" "$currentOpt" "$suffix" "$initrd" \
1024 "false"
1025 done
1026 fi
1027
1028 # If a kdump kernel exists, add crashdump entries
1029 kdumps=$(ls /boot/*-kdump 2>/dev/null || true)
1030 if [ "$kdumps" != "" ] ; then
1031 write_kernel_entry "$kernelVersion" "(crashdump mode)" "$lockalternative" \
1032 "$grub_root_device" "$kernel" "$currentOpt" "crashkernel=64M@16M" "$initrd" \
1033 "false"
1034 fi
1035done
1036
1037memtest86names="memtest86 memtest86+"
1038
1039if test ! x"$memtest86" = x"false" ; then
1040 for name in $memtest86names ; do
1041 if test -f "/boot/$name.bin" ; then
1042 kernelVersion="$name"
1043 kernel="$kernel_dir/$name.bin"
1044 currentOpt=
1045 initrd=
1046
1047 echo "Found kernel: $kernel" >&2
1048
1049 write_kernel_entry "$kernelVersion" "" "" "$grub_root_device" \
1050 "$kernel" "$currentOpt" "" "$initrd" "false" ""
1051 fi
1052 done
1053fi
1054
1055echo $end >> $buffer
1056
1057echo -n "Updating $menu ... " >&2
1058# Insert the new options into the menu
1059if ! grep -q "^$start" $menu ; then
1060 cat $buffer >> $menu
1061 rm -f $buffer
1062else
1063 umask 077
1064 sed -e "/^$start/,/^$end/{
1065 /^$start/r $buffer
1066 d
1067 }
1068 " $menu > $menu.new
1069 cat $menu.new > $menu
1070 rm -f $buffer $menu.new
1071fi
1072
1073# Function to update the default value
1074set_default_value() {
1075 if [ "$use_grub_set_default" = "true" ] ; then
1076 grub-set-default $1
1077 else
1078 value="$1"
1079 newmenu=$(tempfile)
1080 sed -e "s/^[[:blank:]]*default[[:blank:]]*[[:digit:]]*\(.*\)/default ${value}\1/;b" $menu > $newmenu
1081 cat $newmenu > $menu
1082 rm -f $newmenu
1083 unset newmenu
1084 fi
1085}
1086
1087#Updating the default number
1088if test -z "$notChangeDefault"; then
1089 newDefaultNumberPlusOne=$(grep "^[[:blank:]]*title[[:blank:]]*" $menu | grep -n "${defaultEntry}" | cut -f1 -d ":" | sed -ne "1p")
1090 if test -z "$newDefaultNumberPlusOne"; then
1091 echo "Previous default entry removed, resetting to 0">&2
1092 set_default_value "0"
1093 elif test -z "$defaultEntry"; then
1094 echo "Value of default value matches no entry, resetting to 0" >&2
1095 set_default_value "0"
1096 else
1097 if test "$newDefaultNumberPlusOne" = "1"; then
1098 newDefaultNumber="0"
1099 else
1100 newDefaultNumber=$(expr $newDefaultNumberPlusOne - 1)
1101 fi
1102 echo "Updating the default booting kernel">&2
1103 set_default_value "$newDefaultNumber"
1104 fi
1105fi
1106
1107# Function to update the default value
1108set_default_value() {
1109 if [ "$use_grub_set_default" = "true" ] ; then
1110 grub-set-default $1
1111 else
1112 value="$1"
1113 newmenu=$(tempfile)
1114 sed -e "s/^[[:blank:]]*default[[:blank:]]*[[:digit:]]*\(.*\)/default ${value}\1/;b" $menu > $newmenu
1115 cat $newmenu > $menu
1116 rm -f $newmenu
1117 unset newmenu
1118 fi
1119}
1120
1121#Updating the default number
1122if test -z "$notChangeDefault"; then
1123 newDefaultNumberPlusOne=$(grep "^[[:blank:]]*title[[:blank:]]*" $menu | grep -n "${defaultEntry}" | cut -f1 -d ":" | sed -ne "1p")
1124 if test -z "$newDefaultNumberPlusOne"; then
1125 echo "Previous default entry removed, resetting to 0">&2
1126 set_default_value "0"
1127 elif test -z "$defaultEntry"; then
1128 echo "Value of default value matches no entry, resetting to 0" >&2
1129 set_default_value "0"
1130 else
1131 if test "$newDefaultNumberPlusOne" = "1"; then
1132 newDefaultNumber="0"
1133 else
1134 newDefaultNumber=$(expr $newDefaultNumberPlusOne - 1)
1135 fi
1136 echo "Updating the default booting kernel">&2
1137 set_default_value "$newDefaultNumber"
1138 fi
1139fi
1140
1141echo "done" >&2
1142echo >&2