slicefix 9.2 KB
Newer Older
1
2
3
#!/bin/sh
#
# EMULAB-COPYRIGHT
Mike Hibler's avatar
Mike Hibler committed
4
# Copyright (c) 2000-2005, 2007 University of Utah and the Flux Group.
5
6
7
# All rights reserved.
#

Mike Hibler's avatar
Mike Hibler committed
8
9
10
11
if [ -r /etc/emulab/paths.sh ]; then
	. /etc/emulab/paths.sh
else
	BINDIR=/etc/testbed
12
	BOOTDIR=/var/emulab/boot
Mike Hibler's avatar
Mike Hibler committed
13
14
fi

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
disk="ad0"

case $# in
1)
	part=$1
	;;
2)
	part=$1
	disk=$2
	;;
*)
	echo "Usage: $0 partition [disk]"
	exit 1
esac

Mike Hibler's avatar
Mike Hibler committed
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#
# Handle pseudo arguments in the environment.
#   
ACPI=${SLICEFIX_ACPI:-'unknown'}
case $ACPI in
0|no|NO)
    ACPI=no
    ;;
1|yes|YES)
    ACPI=yes
    ;;
*)
    ACPI=unknown
    ;;
esac

46
dofreebsd() {
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
	#
	# ARGH!  FreeBSD 5, which primarily uses UFS2, internally converts
	# UFS1 filesystems to an updated, UFS2 compatible form.  However,
	# some of the converted fields leak back to disk when the filesystem
	# is unmounted, creating the potential for corruption in the following
	# scenerio:
	#
	# 1. mount, update, and unmount a UFS1 FS under FBSD5
	# 2. mount, update, and unmount the FS under FBSD4
	# 3. go back and access the FS under FBSD5
	#
	# #2 will update the old version of the csum structure.  At step
	# #3, the mount will see some of the leaked info from the unmount
	# in #1 and determine that it has already "upgraded" this FS and
	# thus doesn't need to copy the old csum into the new one.  The
	# result is that it will use stale csum info.
	#
	# In theory we could encounter this problem when we slicefix
	# a newly loaded FBSD image (#1), boot up and update stuff on
	# the image (#2), and then create a new image with imagezip
	# (#3, as imagezip uses the FBSD5 filesystem logic).
	#
	# How do we deal with this?  What we will have to do is either
	# fix the FBSD5 filesystem code or we will have to run a little
	# hack after the slicefix unmount to undo the damage that FBSD5
	# does.  Currently I have not done either.  Instead we avoid the
	# problem as follows.  Before making any change to the FS with
	# slicefix, we first RO-mount the FS to see if anything needs to
	# be done.  If not, we just leave it alone.  Since I currently
	# create all new images on machines with "ad" disks and that is
	# what the default fstab contains for its root device, we avoid
	# making any mods with slicefix and thus avoid #1 above.
	#
	# This is clearly not a solution.
	#
Mike Hibler's avatar
Mike Hibler committed
82
	vers=`uname -v | sed -e 's/FreeBSD \([0-9]\).*/\1/'`
83

84
	# see if there is a root ('a') partition on this BSD slice
Mike Hibler's avatar
Mike Hibler committed
85
	`disklabel ${disk}s${part} 2>&1 | grep -s -E '^[ ]+a:' >/dev/null` || {
86
87
88
89
90
91
92
93
94
		return 1
	}

	rootdev=/dev/${disk}s${part}a
	echo "fixing FreeBSD root partition ${disk}s${part}a"
	fsck -p $rootdev || {
		echo "Fsck of $rootdev failed"
		return 1
	}
95
96
97
98
99
	mount -o ro $rootdev /mnt || {
		echo "RO-mount of $rootdev failed"
		return 1
	}

Mike Hibler's avatar
Mike Hibler committed
100
101
102
103
104
	#
	# See if we need to modify anything in the image
	#
	changedisk=0
	changeentropy=0
Mike Hibler's avatar
Mike Hibler committed
105
	changeacpi=0
Mike Hibler's avatar
Mike Hibler committed
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

	# If our disk does not appear anywhere in fstab, we need to fix it
	grep "^/dev/${disk}s" /mnt/etc/fstab >/dev/null 2>&1
	case $? in
	0)
	    ;;
	*)
	    changedisk=1
	    ;;
	esac

	# If there is a /entropy file, we need to update it
	if [ -f /mnt/entropy -a -c /dev/random ]; then
		changeentropy=1
	fi

Mike Hibler's avatar
Mike Hibler committed
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
	#
	# See if we need to change the ACPI setting.
	#
	# If ACPI was not specified via TMCD, leave it along.
	#
	# If "acpi_load" does not appear at all in the loader.conf file,
	# assume the OS cannot handle it (or that we do not know how to
	# change it) and leave it alone.
	#
	if [ $ACPI != "unknown" ]; then
	    grep "acpi_load=" /mnt/boot/loader.conf >/dev/null 2>&1
	    case $? in
	    0)
		grep "^acpi_load=\"YES\"" /mnt/boot/loader.conf >/dev/null 2>&1
		case $? in
		0)
		    if [ $ACPI = "no" ]; then
			changeacpi=1
		    fi
		    ;;
		*)
		    if [ $ACPI = "yes" ]; then
			changeacpi=1
		    fi
		    ;;
		esac
		;;
	    *)
		;;
	    esac
	fi

	if [ $changedisk -eq 0 -a $changeentropy -eq 0 -a $changeacpi -eq 0 ]; then
		echo "  no changes necessary"
156
157
158
159
160
161
		umount $rootdev
		return 0
	fi

	# We need to change something, remount RW and change it
	umount $rootdev
162
163
164
165
	mount $rootdev /mnt || {
		echo "Mount of $rootdev failed"
		return 1
	}
Mike Hibler's avatar
Mike Hibler committed
166
167

	if [ $changedisk -eq 1 ]; then
168
	    echo "  updating /etc/fstab"
Mike Hibler's avatar
Mike Hibler committed
169
	    sed -E -i .orig -e "s;^/dev/[a-zA-Z]+[0-9]+s[0-9]+;/dev/${disk}s${part};" /mnt/etc/fstab || {
170
171
172
		echo "Failed to update /etc/fstab"
		umount $rootdev
		return 1
Mike Hibler's avatar
Mike Hibler committed
173
	    }
174
	    echo "  updating /etc/dumpdates"
Mike Hibler's avatar
Mike Hibler committed
175
	    sed -E -i .orig -e "s;^/dev/[a-zA-Z]+[0-9]+s[0-9]+;/dev/${disk}s${part};" /mnt/etc/dumpdates || {
176
177
178
		echo "Failed to update /etc/dumpdates"
		umount $rootdev
		return 1
Mike Hibler's avatar
Mike Hibler committed
179
180
181
182
183
184
185
186
	    }
	fi

	if [ $changeentropy -eq 1 ]; then
	    echo "  updating /entropy"
	    dd if=/dev/random of=/mnt/entropy bs=4096 count=1 >/dev/null 2>&1
	fi

Mike Hibler's avatar
Mike Hibler committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
	if [ $changeacpi -eq 1 ]; then
	    if [ $ACPI = "no" ]; then
		on="dis"
	    else
		on="en"
	    fi
	    echo "  ${on}abling ACPI"
	    sed -E -i .orig -e "/[Aa][Cc][Pp][Ii]/d" /mnt/boot/loader.conf || {
		echo "Failed to update /boot/loader.conf"
		umount $rootdev
		return 1
	    }
	    if [ $ACPI = "no" ]; then
		cat <<EOF1 >>/mnt/boot/loader.conf
# disable ACPI
acpi_load="NO"
hint.acpi.0.disabled=1
loader.acpi_disabled_by_user=1
EOF1
	    else
		cat <<EOF2 >>/mnt/boot/loader.conf
# enable ACPI
acpi_load="YES"
hint.acpi.0.disabled=0
EOF2
	    fi
	fi

215
	umount $rootdev
216
217

	# XXX need to fixup FS, see big comment above
Mike Hibler's avatar
Mike Hibler committed
218
219
	if [ "x$vers" != "x4" ]; then
		echo "WARNING: FBSD${vers} may have modified the UFS1 root FS"
220
221
	fi

222
223
224
	return 0
}

225
226
227
228
229
#
# echo the name of the kernel that lilo will boot by default
#
lilogetkernel() {
    _lconf=$1
Mike Hibler's avatar
Nits:    
Mike Hibler committed
230
    _re='[a-zA-Z0-9][-_\.a-zA-Z0-9]*'
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246

    # see if there is a default= line and prefer that
    linux=`grep -E "default=$_re" $_lconf | sed -e "s/default=\($_re\).*/\1/"`

    # no explicit default, use first kernel listed
    if [ "x${linux}" = x ]; then
	linux=`grep -E "label=$_re" $_lconf | head -1 | \
		sed -e "s/label=\($_re\).*/\1/"`
    fi

    # still no hit, just use 'linux'
    linux=${linux:-'linux'}

    echo $linux
}

247
dolinux() {
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
	# figure out the linux device name
	dunit=`echo $disk | sed -e 's/..\([0-7]\)/\1/'`
	case $disk in
	# IDE
	ad[0-3])
		dtype="hd"
		d=`echo $dunit | sed -e 'y/0123/048c/'`
		lrootdev="3${d}${part}"
		;;
	# SATA
	ad[4-7])
		dtype="sd"
		dunit=`expr $dunit - 4`
		lrootdev="8${dunit}${part}"
		;;
	# SCSI
	da[0-7])
		dtype="sd"
		lrootdev="8${dunit}${part}"
Mike Hibler's avatar
Mike Hibler committed
267
268
269
270
271
272
		;;
	# Megaraid
	amrd[0-7])
		dunit=`echo $disk | sed -e 's/amrd\([0-7]\)/\1/'`
		dtype="sd"
		lrootdev="8${dunit}${part}"
273
274
275
276
277
278
279
280
281
282
283
		;;
	*)
		echo "slicefix: linux: unknown disk $disk"
		return 1
		;;
	esac
	dunit=`echo $dunit | sed -e 'y/01234567/abcdefgh/'`;
	ldisk=$dtype$dunit

	# attempt to mount filesystem   
	rootdev=/dev/${disk}s${part}
Mike Hibler's avatar
Mike Hibler committed
284
	echo "fixing Linux root partition ${disk}s${part}"
285
286
287
288
289
290
291
292
293
294
295
296
	mount -t ext2fs $rootdev /mnt || {
		echo "EXT2FS mount of $rootdev failed"
		return 1
	}

	# change the swap devices in fstab
	sed -i .orig -e "s;^/dev/[hs]d.\([0-7]\);/dev/${ldisk}\1;" /mnt/etc/fstab || {
		echo "Failed to update /etc/fstab"
		umount $rootdev
		return 1
	}

297
298
299
300
301
302
303
304
305
306
307
	#
	# If there's a GRUB config file, update all root=X kernel params.
	#
	gconf=/mnt/boot/grub/grub.conf
	if [ -r $gconf ]; then
	    echo "  updating /boot/grub/grub.conf"
	    sed -i .orig -e "s;\([br]oot=/dev\)/[hs]d.\([0-7]\);\1/${ldisk}\2;" $gconf || {
		echo "Failed to update /boot/boot/grub/grub.conf"
	    }
	fi

308
309
310
311
312
313
314
	#
	# If using lilo, update lilo.conf and set indicator to tell Emulab
	# to rerun lilo.
	#
	linux=
	lconf=/mnt/etc/lilo.conf
	if [ -r $lconf ]; then
Mike Hibler's avatar
Mike Hibler committed
315
	    echo "  updating /etc/lilo.conf"
316
317
318
319
320
	    sed -i .orig -e "s;\([br]oot=/dev\)/[hs]d.\([0-7]\);\1/${ldisk}\2;" $lconf || {
		    echo "Failed to update /etc/lilo.conf"
		    umount $rootdev
		    return 1
	    }
321

322
323
324
325
	    # XXX note the hardwired path, cannot use BOOTDIR as it is
	    # different in frisbee MFS.  This also assumes Linux partition
	    # is one big filesystem.
	    cp /dev/null /mnt/var/emulab/boot/runlilo
326

327
328
329
	    # grab the default linux kernel to boot
	    linux=`lilogetkernel $lconf`
	fi
330

331
332
333
334
335
	if [ -f /mnt/var/lib/random-seed -a -c /dev/urandom ]; then
	    echo "  updating /var/lib/random-seed"
	    dd if=/dev/urandom of=/mnt/var/lib/random-seed bs=512 count=1 >/dev/null 2>&1
	fi

336
337
	umount $rootdev

338
	if [ "x${linux}" != x ]; then
Mike Hibler's avatar
Mike Hibler committed
339
	    echo -n "  "
340
341
	    # setup one time lilo command line, must be done after unmount
	    $BINDIR/groklilo -c "$linux root=$lrootdev" $part /dev/$disk || {
342
343
		echo "Failed to set LILO command line"
		return 1
344
345
	    }
	fi
346

Mike Hibler's avatar
Mike Hibler committed
347
	return 0
348
349
}

Mike Hibler's avatar
Mike Hibler committed
350
351
fixone() {
    echo "*** ${disk}s${part}:"
352
    ptype=`fdisk -${part} ${disk} | grep sysid | sed 's/^sysid \([0-9][0-9]*\).*/\1/'`
Mike Hibler's avatar
Mike Hibler committed
353
354
355
356
    ptype=${ptype:-0}

    case $ptype in
    165)
357
	dofreebsd
Mike Hibler's avatar
Mike Hibler committed
358
	return $?
359
	;;
Mike Hibler's avatar
Mike Hibler committed
360
361
362
    131)
	dolinux
	return $?
363
	;;
Mike Hibler's avatar
Mike Hibler committed
364
365
366
367
368
369
    130)
	echo "ignoring Linux swap partition"
	;;
    7)
	echo "ignoring NTFS partition"
	;;
Mike Hibler's avatar
Mike Hibler committed
370
    0)
Mike Hibler's avatar
Mike Hibler committed
371
	echo "ignoring unused partition"
Mike Hibler's avatar
Mike Hibler committed
372
373
	;;
    *)
374
375
	echo "ignoring partition type $ptype"
	;;
Mike Hibler's avatar
Mike Hibler committed
376
377
378
379
380
381
382
383
384
385
386
    esac
    return 0
}

case $part in
0)
    part=1; fixone
    part=2; fixone
    part=3; fixone
    part=4; fixone

387
388
389
390
391
    # when fixing all partitions, do not fail on an error
    if [ $? -ne 0 ]; then
    	echo "WARNING: failed to fix one or more partitions, BEWARE!"
    fi

Mike Hibler's avatar
Mike Hibler committed
392
393
394
395
396
397
398
399
400
401
402
403
    # for the CD boot, we need to intialize the magic boot block
    if [ -e /cdrom.inf -a -x $BINDIR/tbbootconfig ]; then
	$BINDIR/tbbootconfig -f -c 1 -k 0 -m 1 /dev/${disk}
    fi
    ;;
1|2|3|4)
    fixone
    ;;
*)
    echo "bad partition: $part"
    false
    ;;
404
405
esac

Mike Hibler's avatar
Mike Hibler committed
406
exit $?