Project

General

Profile

Download (12.9 KB) Statistics
| Branch: | Tag: | Revision:
1
#! /bin/sh
2

    
3
# Install GRUB on your drive.
4
#   Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc.
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
# Initialize some variables.
21
prefix=/usr/local
22
exec_prefix=${prefix}
23
sbindir=${exec_prefix}/sbin
24
libdir=/usr/local/share
25
PACKAGE=grub
26
VERSION=0.97
27
host_cpu=i386
28
host_os=freebsd7.0
29
host_vendor=freebsd
30
pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor}
31

    
32
grub_shell=${sbindir}/grub
33
grub_set_default=${sbindir}/grub-set-default
34
log_file=/tmp/grub-install.log.$$
35
img_file=/tmp/grub-install.img.$$
36
rootdir=
37
grub_prefix=/boot/grub
38

    
39
install_device=
40
no_floppy=
41
force_lba=
42
recheck=no
43
debug=no
44

    
45
# look for secure tempfile creation wrappers on this platform
46
if test -x /bin/tempfile; then
47
    mklog="/bin/tempfile --prefix=grub"
48
    mkimg="/bin/tempfile --prefix=grub"
49
elif test -x /bin/mktemp; then
50
    mklog="/bin/mktemp /tmp/grub-install.log.XXXXXX"
51
    mkimg="/bin/mktemp /tmp/grub-install.img.XXXXXX"
52
else
53
    mklog=""
54
    mkimg=""
55
fi
56

    
57
# Usage: usage
58
# Print the usage.
59
usage () {
60
    cat <<EOF
61
Usage: grub-install [OPTION] install_device
62
Install GRUB on your drive.
63

    
64
  -h, --help              print this message and exit
65
  -v, --version           print the version information and exit
66
  --root-directory=DIR    install GRUB images under the directory DIR
67
                          instead of the root directory
68
  --grub-shell=FILE       use FILE as the grub shell
69
  --no-floppy             do not probe any floppy drive
70
  --force-lba             force GRUB to use LBA mode even for a buggy
71
                          BIOS
72
  --recheck               probe a device map even if it already exists
73

    
74
INSTALL_DEVICE can be a GRUB device name or a system device filename.
75

    
76
grub-install copies GRUB images into the DIR/boot directory specfied by
77
--root-directory, and uses the grub shell to install grub into the boot
78
sector.
79

    
80
Report bugs to <bug-grub@gnu.org>.
81
EOF
82
}
83

    
84
# Usage: convert os_device
85
# Convert an OS device to the corresponding GRUB drive.
86
# This part is OS-specific.
87
convert () {
88
    # First, check if the device file exists.
89
    if test -e "$1"; then
90
	:
91
    else
92
	echo "$1: Not found or not a block device." 1>&2
93
	exit 1
94
    fi
95

    
96
    # Break the device name into the disk part and the partition part.
97
    case "$host_os" in
98
    linux*)
99
	tmp_disk=`echo "$1" | sed -e 's%\([sh]d[a-z]\)[0-9]*$%\1%' \
100
				  -e 's%\(d[0-9]*\)p[0-9]*$%\1%' \
101
				  -e 's%\(fd[0-9]*\)$%\1%' \
102
				  -e 's%/part[0-9]*$%/disc%' \
103
				  -e 's%\(c[0-7]d[0-9]*\).*$%\1%'`
104
	tmp_part=`echo "$1" | sed -e 's%.*/[sh]d[a-z]\([0-9]*\)$%\1%' \
105
				  -e 's%.*d[0-9]*p%%' \
106
				  -e 's%.*/fd[0-9]*$%%' \
107
				  -e 's%.*/floppy/[0-9]*$%%' \
108
				  -e 's%.*/\(disc\|part\([0-9]*\)\)$%\2%' \
109
				  -e 's%.*c[0-7]d[0-9]*p%%'`
110
	;;
111
    gnu*)
112
	tmp_disk=`echo "$1" | sed 's%\([sh]d[0-9]*\).*%\1%'`
113
	tmp_part=`echo "$1" | sed "s%$tmp_disk%%"` ;;
114
    freebsd[234]* | kfreebsd*-gnu)
115
	tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%r\1%' \
116
			    | sed 's%r\{0,1\}\(da[0-9]*\).*$%r\1%'`
117
	tmp_part=`echo "$1" \
118
	    | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
119
       	    | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
120
	;;
121
    freebsd[567]*)
122
	tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([saw]d[0-9]*\).*$%\1%' \
123
			    | sed 's%r\{0,1\}\(da[0-9]*\).*$%\1%'`
124
	tmp_part=`echo "$1" \
125
	    | sed "s%.*/r\{0,1\}[saw]d[0-9]\(s[0-9]*[a-h]\)%\1%" \
126
       	    | sed "s%.*/r\{0,1\}da[0-9]\(s[0-9]*[a-h]\)%\1%"`
127
	;;
128
    netbsd* | knetbsd*-gnu)
129
	tmp_disk=`echo "$1" | sed 's%r\{0,1\}\([sw]d[0-9]*\).*$%r\1d%' \
130
	    | sed 's%r\{0,1\}\(fd[0-9]*\).*$%r\1a%'`
131
	tmp_part=`echo "$1" \
132
	    | sed "s%.*/r\{0,1\}[sw]d[0-9]\([abe-p]\)%\1%"`
133
	;;
134
    *)
135
	echo "grub-install does not support your OS yet." 1>&2
136
	exit 1 ;;
137
    esac
138

    
139
    # Get the drive name.
140
    tmp_drive=`grep -v '^#' $device_map | grep "$tmp_disk *$" \
141
	| sed 's%.*\(([hf]d[0-9][a-g0-9,]*)\).*%\1%'`
142

    
143
    # If not found, print an error message and exit.
144
    if test "x$tmp_drive" = x; then
145
	echo "$1 does not have any corresponding BIOS drive." 1>&2
146
	exit 1
147
    fi
148

    
149
    if test "x$tmp_part" != x; then
150
	# If a partition is specified, we need to translate it into the
151
	# GRUB's syntax.
152
	case "$host_os" in
153
	linux*)
154
	    echo "$tmp_drive" | sed "s%)$%,`expr $tmp_part - 1`)%" ;;
155
	gnu*)
156
	    if echo $tmp_part | grep "^s" >/dev/null; then
157
		tmp_pc_slice=`echo $tmp_part \
158
		    | sed "s%s\([0-9]*\)[a-g]*$%\1%"`
159
		tmp_drive=`echo "$tmp_drive" \
160
		    | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
161
	    fi
162
	    if echo $tmp_part | grep "[a-g]$" >/dev/null; then
163
		tmp_bsd_partition=`echo "$tmp_part" \
164
		    | sed "s%[^a-g]*\([a-g]\)$%\1%"`
165
		tmp_drive=`echo "$tmp_drive" \
166
		    | sed "s%)%,$tmp_bsd_partition)%"`
167
	    fi
168
	    echo "$tmp_drive" ;;
169
	freebsd* | kfreebsd*-gnu)
170
	    if echo $tmp_part | grep "^s" >/dev/null; then
171
		tmp_pc_slice=`echo $tmp_part \
172
		    | sed "s%s\([0-9]*\)[a-h]*$%\1%"`
173
		tmp_drive=`echo "$tmp_drive" \
174
		    | sed "s%)%,\`expr "$tmp_pc_slice" - 1\`)%"`
175
	    fi
176
	    if echo $tmp_part | grep "[a-h]$" >/dev/null; then
177
		tmp_bsd_partition=`echo "$tmp_part" \
178
		    | sed "s%s\{0,1\}[0-9]*\([a-h]\)$%\1%"`
179
		tmp_drive=`echo "$tmp_drive" \
180
		    | sed "s%)%,$tmp_bsd_partition)%"`
181
	    fi
182
	    echo "$tmp_drive" ;;
183
	netbsd* | knetbsd*-gnu)
184
	    if echo $tmp_part | grep "^[abe-p]$" >/dev/null; then
185
		tmp_bsd_partition=`echo "$tmp_part" \
186
		    | sed "s%\([a-p]\)$%\1%"`
187
		tmp_drive=`echo "$tmp_drive" \
188
		    | sed "s%)%,$tmp_bsd_partition)%"`
189
	    fi
190
	    echo "$tmp_drive" ;;
191
	esac
192
    else
193
	# If no partition is specified, just print the drive name.
194
	echo "$tmp_drive"
195
    fi
196
}
197

    
198
# Usage: resolve_symlink file
199
# Find the real file/device that file points at
200
resolve_symlink () {
201
	tmp_fname=$1
202
	# Resolve symlinks
203
	while test -L $tmp_fname; do
204
		tmp_new_fname=`ls -al $tmp_fname | sed -n 's%.*-> \(.*\)%\1%p'`
205
		if test -z "$tmp_new_fname"; then
206
			echo "Unrecognized ls output" 2>&1
207
			exit 1
208
		fi
209

    
210
		# Convert relative symlinks
211
		case $tmp_new_fname in
212
			/*) tmp_fname="$tmp_new_fname"
213
			;;
214
			*) tmp_fname="`echo $tmp_fname | sed 's%/[^/]*$%%'`/$tmp_new_fname"
215
			;;
216
		esac
217
	done
218
	echo "$tmp_fname"
219
}
220

    
221
# Usage: find_device file
222
# Find block device on which the file resides.
223
find_device () {
224
    # For now, this uses the program `df' to get the device name, but is
225
    # this really portable?
226
    tmp_fname=`df $1/ | sed -n 's%.*\(/dev/[^ 	]*\).*%\1%p'`
227

    
228
    if test -z "$tmp_fname"; then
229
	echo "Could not find device for $1" 2>&1
230
	exit 1
231
    fi
232

    
233
	tmp_fname=`resolve_symlink $tmp_fname`
234

    
235
    echo "$tmp_fname"
236
}
237

    
238
# Check the arguments.
239
for option in "$@"; do
240
    case "$option" in
241
    -h | --help)
242
	usage
243
	exit 0 ;;
244
    -v | --version)
245
	echo "grub-install (GNU GRUB ${VERSION})"
246
	exit 0 ;;
247
    --root-directory=*)
248
	rootdir=`echo "$option" | sed 's/--root-directory=//'` ;;
249
    --grub-shell=*)
250
	grub_shell=`echo "$option" | sed 's/--grub-shell=//'` ;;
251
    --no-floppy)
252
	no_floppy="--no-floppy" ;;
253
    --force-lba)
254
	force_lba="--force-lba" ;;
255
    --recheck)
256
	recheck=yes ;;
257
    # This is an undocumented feature...
258
    --debug)
259
	debug=yes ;;
260
    -*)
261
	echo "Unrecognized option \`$option'" 1>&2
262
	usage
263
	exit 1
264
	;;
265
    *)
266
	if test "x$install_device" != x; then
267
	    echo "More than one install_devices?" 1>&2
268
	    usage
269
	    exit 1
270
	fi
271
	install_device="${option}" ;;
272
    esac
273
done
274

    
275
if test "x$install_device" = x; then
276
    echo "install_device not specified." 1>&2
277
    usage
278
    exit 1
279
fi
280

    
281
# If the debugging feature is enabled, print commands.
282
if test $debug = yes; then
283
    set -x
284
fi
285

    
286
# Initialize these directories here, since ROOTDIR was initialized.
287
case "$host_os" in
288
netbsd* | openbsd*)
289
    # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub
290
    # instead of /boot/grub.
291
    grub_prefix=/grub
292
    bootdir=${rootdir}
293
    ;;
294
*)
295
    # Use /boot/grub by default.
296
    bootdir=${rootdir}/boot
297
    ;;
298
esac
299

    
300
grubdir=${bootdir}/grub
301
device_map=${grubdir}/device.map
302

    
303
# Check if GRUB is installed.
304
# This is necessary, because the user can specify "grub --read-only".
305
set $grub_shell dummy
306
if test -f "$1"; then
307
    :
308
else
309
    echo "$1: Not found." 1>&2
310
    exit 1
311
fi
312

    
313
if test -f "$pkglibdir/stage1"; then
314
    :
315
else
316
    echo "${pkglibdir}/stage1: Not found." 1>&2
317
    exit 1
318
fi
319

    
320
if test -f "$pkglibdir/stage2"; then
321
    :
322
else
323
    echo "${pkglibdir}/stage2: Not found." 1>&2
324
    exit 1
325
fi
326

    
327
# Don't check for *stage1_5, because it is not fatal even if any
328
# Stage 1.5 does not exist.
329

    
330
# Create the GRUB directory if it is not present.
331
test -d "$bootdir" || mkdir "$bootdir" || exit 1
332
test -d "$grubdir" || mkdir "$grubdir" || exit 1
333

    
334
# If --recheck is specified, remove the device map, if present.
335
if test $recheck = yes; then
336
    rm -f $device_map
337
fi
338

    
339
# Create the device map file if it is not present.
340
if test -f "$device_map"; then
341
    :
342
else
343
    # Create a safe temporary file.
344
    test -n "$mklog" && log_file=`$mklog`
345

    
346
    $grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
347
quit
348
EOF
349
    if grep "Error [0-9]*: " $log_file >/dev/null; then
350
	cat $log_file 1>&2
351
	exit 1
352
    fi
353

    
354
    rm -f $log_file
355
fi
356

    
357
# Make sure that there is no duplicated entry.
358
tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
359
    | sort | uniq -d | sed -n 1p`
360
if test -n "$tmp"; then
361
    echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
362
    exit 1
363
fi
364

    
365
# Check for INSTALL_DEVICE.
366
case "$install_device" in
367
/dev/*)
368
    install_device=`resolve_symlink "$install_device"`
369
    install_drive=`convert "$install_device"`
370
    # I don't know why, but some shells wouldn't die if exit is
371
    # called in a function.
372
    if test "x$install_drive" = x; then
373
	exit 1
374
    fi ;;
375
\([hf]d[0-9]*\))
376
    install_drive="$install_device" ;;
377
[hf]d[0-9]*)
378
    # The GRUB format with no parenthesis.
379
    install_drive="($install_device)" ;;
380
*)
381
    echo "Format of install_device not recognized." 1>&2
382
    usage
383
    exit 1 ;;
384
esac
385

    
386
# Get the root drive.
387
root_device=`find_device ${rootdir}`
388
bootdir_device=`find_device ${bootdir}`
389

    
390
# Check if the boot directory is in the same device as the root directory.
391
if test "x$root_device" != "x$bootdir_device"; then
392
    # Perhaps the user has a separate boot partition.
393
    root_device=$bootdir_device
394
    grub_prefix="/grub"
395
fi
396

    
397
# Convert the root device to a GRUB drive.
398
root_drive=`convert "$root_device"`
399
if test "x$root_drive" = x; then
400
    exit 1
401
fi
402

    
403
# Check if the root directory exists in the same device as the grub
404
# directory.
405
grubdir_device=`find_device ${grubdir}`
406

    
407
if test "x$grubdir_device" != "x$root_device"; then
408
    # For now, cannot deal with this situation.
409
    cat <<EOF 1>&2
410
You must set the root directory by the option --root-directory, because
411
$grubdir does not exist in the root device $root_device.
412
EOF
413
    exit 1
414
fi
415

    
416
# Copy the GRUB images to the GRUB directory.
417
for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
418
    rm -f $file || exit 1
419
done
420
for file in \
421
    ${pkglibdir}/stage1 ${pkglibdir}/stage2 ${pkglibdir}/*stage1_5; do
422
    cp -f $file ${grubdir} || exit 1
423
done
424

    
425
# Make a default file.
426
${grub_set_default} --root-directory=${rootdir} default
427

    
428
# Make sure that GRUB reads the same images as the host OS.
429
test -n "$mkimg" && img_file=`$mkimg`
430
test -n "$mklog" && log_file=`$mklog`
431

    
432
for file in ${grubdir}/stage1 ${grubdir}/stage2 ${grubdir}/*stage1_5; do
433
    count=5
434
    tmp=`echo $file | sed "s|^${grubdir}|${grub_prefix}|"`
435
    while test $count -gt 0; do
436
	$grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
437
dump ${root_drive}${tmp} ${img_file}
438
quit
439
EOF
440
	if grep "Error [0-9]*: " $log_file >/dev/null; then
441
	    :
442
	elif cmp $file $img_file >/dev/null; then
443
	    break
444
	fi
445
	sleep 1
446
	count=`expr $count - 1`    
447
    done
448
    if test $count -eq 0; then
449
	echo "The file $file not read correctly." 1>&2
450
	echo
451
    fi
452
done
453

    
454
rm -f $img_file
455
rm -f $log_file
456

    
457
# Create a safe temporary file.
458
test -n "$mklog" && log_file=`$mklog`
459

    
460
# Now perform the installation.
461
$grub_shell --batch $no_floppy --device-map=$device_map <<EOF >$log_file
462
root $root_drive
463
setup $force_lba --stage2=$grubdir/stage2 --prefix=$grub_prefix $install_drive
464
quit
465
EOF
466

    
467
if grep "Error [0-9]*: " $log_file >/dev/null || test $debug = yes; then
468
    cat $log_file 1>&2
469
    exit 1
470
fi
471

    
472
rm -f $log_file
473

    
474
# Prompt the user to check if the device map is correct.
475
echo "Installation finished. No error reported."
476
echo "This is the contents of the device map $device_map."
477
echo "Check if this is correct or not. If any of the lines is incorrect,"
478
echo "fix it and re-run the script \`grub-install'."
479
echo
480

    
481
cat $device_map
482

    
483
# Bye.
484
exit 0
(3-3/15)