Project

General

Profile

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

    
3
# /etc/rc.firmware
4
# originally part of m0n0wall (http://neon1.net/m0n0wall)
5
# Copyright (C) 2005-2009 Scott Ullrich <sullrich@pfsense.org>.
6
# Copyright (C) 2003 Manuel Kasper <mk@neon1.net>.
7
# All rights reserved.
8

    
9
# mount /cf
10
/etc/rc.conf_mount_rw
11

    
12
# Reset file(s)
13
echo "" >/conf/upgrade_log.txt
14
echo "" >/conf/firmware_update_misc_log.txt
15
echo "" >/conf/fdisk_upgrade_log.txt
16

    
17
exec 3>&2 2>>/conf/firmware_update_misc_log.txt
18

    
19
export ACTION=$1
20
export IMG=$2
21
if [ $# -eq 3 ]; then
22
	export CUSTOMIMG=$3
23
fi
24

    
25
file_notice() {
26
	/usr/local/bin/php-cgi -q -d auto_prepend_file=config.inc <<ENDOFF
27
	<?php
28
		require_once("globals.inc");
29
		require_once("functions.inc");
30
		file_notice("$1", "$2", "$1", "");
31
	?>
32
ENDOFF
33
}
34

    
35
output_env_to_log() {
36
	date >> /conf/upgrade_log.txt
37
	echo "" >> /conf/upgrade_log.txt
38

    
39
	ls -lah /dev/ >> /conf/upgrade_log.txt
40
	echo "" >> /conf/upgrade_log.txt
41

    
42
	ls -lah $IMG >> /conf/upgrade_log.txt
43
	echo "" >> /conf/upgrade_log.txt
44

    
45
	md5 $IMG >> /conf/upgrade_log.txt
46
	echo "" >> /conf/upgrade_log.txt
47

    
48
	mount >> /conf/upgrade_log.txt
49
	echo "" >> /conf/upgrade_log.txt
50

    
51
	top >> /conf/upgrade_log.txt
52
	echo "" >> /conf/upgrade_log.txt
53
}
54

    
55
backup_chflags() {
56
	TOPROCESS="bin lib libexec sbin usr"
57
	for files in $TOPROCESS; do
58
		/usr/sbin/mtree -Pcp /${files} | bzip2 -9 > /tmp/chflags.dist.${files}.bz2 2>> /conf/upgrade_log.txt
59
	done
60
}
61

    
62
restore_chflags() {
63
	TOPROCESS="bin lib libexec sbin usr"
64
	for files in $TOPROCESS; do
65
		cd / && /usr/bin/bzcat /tmp/chflags.dist.${files}.bz2 | /usr/sbin/mtree -P -p /${files} >> /conf/upgrade_log.txt 2>&1
66
	done
67
}
68

    
69
remove_chflags() {
70
	TOPROCESS="bin lib libexec sbin usr"
71
	for files in $TOPROCESS; do
72
		/bin/chflags -R noschg /${files}
73
		/bin/chmod -R u+rw /${files}
74
	done
75
}
76

    
77
case $ACTION in
78
enable)
79
	touch /conf/upgrade_log.txt
80
	echo "" >> /conf/upgrade_log.txt
81
	echo "Enable" >> /conf/upgrade_log.txt
82
	echo "" >> /conf/upgrade_log.txt
83
	/etc/rc.conf_mount_ro
84
	;;
85
auto)
86
	touch /var/run/firmwarelock.dirty
87
	backup_chflags
88
	remove_chflags
89
	/etc/rc.firmware_auto
90
	restore_chflags
91
	/etc/rc.conf_mount_ro
92
	;;
93
pfSenseNanoBSDupgrade)
94

    
95
	# Sanity check - bail early if there's no firmware file!
96
	if [ ! -r $IMG ]; then
97
		echo "2nd parameter has not been passed or file does not exist. Exiting." >> /conf/upgrade_log.txt 2>&1
98
		/etc/rc.conf_mount_ro
99
		exit 1
100
	fi
101

    
102
	# Prevent full upgrade file from being used to upgrade
103
	if [ `echo $IMG | grep "full"` ]; then
104
		echo "You cannot use a full file for upgrade.  Please use a file labelled nanobsd upgrade."
105
		file_notice "NanoBSDUpgradeFailure" "You have attempted to use a full NanoBSD installation file as an upgrade.  Please use a NanoBSD file labelled 'upgrade' instead."
106
		rm -f $IMG
107
		/etc/rc.conf_mount_ro
108
		exit 1
109
	fi
110

    
111
	touch /var/run/firmwarelock.dirty
112

    
113
	echo "NanoBSD Firmware upgrade in progress..." >> /conf/upgrade_log.txt 2>&1
114
	echo "NanoBSD Firmware upgrade in progress..." | wall
115
	/etc/rc.notify_message -e -g -m "NanoBSD Firmware upgrade in progress..."
116

    
117
	# backup config
118
	/bin/mkdir -p /tmp/configbak
119
	cp -Rp /conf/* /tmp/configbak 2>/dev/null
120

    
121
	# Remove logs from backup dir to avoid clobbering upon restore.
122
	rm /tmp/configbak/*_log.txt 2>/dev/null
123

    
124
	echo "" >> /conf/upgrade_log.txt
125

    
126
	echo "Installing ${IMG}." >> /conf/upgrade_log.txt 2>&1
127
	echo "Installing ${IMG}." | wall
128

    
129
	# resolve glabel label that we booted from
130
	BOOT_DEVICE=`/sbin/mount | /usr/bin/grep pfsense | /usr/bin/cut -d'/' -f4 | /usr/bin/cut -d' ' -f1`
131
	# resolve glabel to the real boot dev entry
132
	REAL_BOOT_DEVICE=`/sbin/glabel list | /usr/bin/grep -B2 ufs/${BOOT_DEVICE} | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' '`
133
	# grab the boot device, example ad1, ad0
134
	BOOT_DRIVE=`/sbin/glabel list | /usr/bin/grep -B2 ufs/pfsense | /usr/bin/head -n 1 | /usr/bin/cut -f3 -d' ' | /usr/bin/cut -d's' -f1`
135
	# test the slice.  if we are on slice 1 we need to flash 2 and vice versa
136
	if [ `echo $REAL_BOOT_DEVICE | /usr/bin/grep "s1"` ]; then
137
		SLICE="2"
138
		OLDSLICE="1"
139
		TOFLASH="${BOOT_DRIVE}s${SLICE}"
140
		COMPLETE_PATH="${BOOT_DRIVE}s${SLICE}a"
141
		GLABEL_SLICE="pfsense1"
142
		UFS_ID="1"
143
		OLD_UFS_ID="0"
144
	else
145
		SLICE="1"
146
		OLDSLICE="2"
147
		TOFLASH="${BOOT_DRIVE}s${SLICE}"
148
		COMPLETE_PATH="${BOOT_DRIVE}s${SLICE}a"
149
		GLABEL_SLICE="pfsense0"
150
		UFS_ID="0"
151
		OLD_UFS_ID="1"
152
	fi
153

    
154
	# Output specific information that this script is using
155
	echo "SLICE         ${SLICE}" >> /conf/upgrade_log.txt
156
	echo "OLDSLICE      ${OLDSLICE}" >> /conf/upgrade_log.txt
157
	echo "TOFLASH       ${TOFLASH}" >> /conf/upgrade_log.txt
158
	echo "COMPLETE_PATH ${COMPLETE_PATH}" >> /conf/upgrade_log.txt
159
	echo "GLABEL_SLICE  ${GLABEL_SLICE}" >> /conf/upgrade_log.txt
160

    
161
	# First ensure the new file can fit inside the
162
	# slice that we are going to be operating on.
163
	NEW_IMG_SIZE=`echo $((\`gzip -l ${IMG} | grep -v compressed | awk '{ print $2}'\` / 1024 / 1024))`
164
	SIZE=`/sbin/fdisk ${COMPLETE_PATH} | /usr/bin/grep Meg | /usr/bin/awk '{ print $5 }' | /usr/bin/cut -d"(" -f2`
165
	# USB slices are under-reported even more than CF slices when viewed
166
	# directly, instead of when looking at the entire disk. Compensate
167
	# by adding exactly 6MB. 4MB was consistently 2MB too few, and
168
	# was resulting in failing upgrades on USB Flash based installs.
169
	SIZE=`expr $SIZE + 6`
170
	if [ "$SIZE" -lt "$NEW_IMG_SIZE" ]; then
171
		file_notice "UpgradeFailure" "Upgrade failed due to the upgrade image being larger than the partition that is configured on disk.  Halting. Size on disk: $SIZE < Size of new image: $NEW_IMG_SIZE"
172
		echo "Upgrade failed.  Please check the system log file for more information" | wall
173
		rm -f $IMG
174
		rm -f /var/run/firmwarelock.dirty
175
		rm -f /var/run/firmware.lock
176
		rm -f ${IMG}
177
		/etc/rc.conf_mount_ro
178
		exit 1
179
	fi
180

    
181
	# Output environment information to log file
182
	output_env_to_log
183

    
184
	# Grab a before upgrade look at fdisk
185
	echo "" >> /conf/fdisk_upgrade_log.txt
186
	echo "Before upgrade fdisk/bsdlabel" >> /conf/fdisk_upgrade_log.txt
187
	fdisk $BOOT_DRIVE >> /conf/fdisk_upgrade_log.txt
188
	bsdlabel -A ${BOOT_DRIVE}s1 >> /conf/fdisk_upgrade_log.txt
189
	bsdlabel -A ${BOOT_DRIVE}s2 >> /conf/fdisk_upgrade_log.txt
190
	bsdlabel -A ${BOOT_DRIVE}s3 >> /conf/fdisk_upgrade_log.txt
191
	echo "---------------------------------------------------------------" >> /conf/fdisk_upgrade_log.txt
192
	echo "" >> /conf/fdisk_upgrade_log.txt
193

    
194
	# Log that we are really doing a NanoBSD upgrade
195
	echo "" >> /conf/upgrade_log.txt
196
	echo "NanoBSD upgrade starting" >> /conf/upgrade_log.txt
197
	echo "" >> /conf/upgrade_log.txt
198

    
199
	# Remove TOFLASH and get ready for new flash image
200
	echo "" >> /conf/upgrade_log.txt
201
	echo "dd if=/dev/zero of=/dev/${TOFLASH} bs=1m count=1" >> /conf/upgrade_log.txt
202
	dd if=/dev/zero of=/dev/${TOFLASH} bs=1m count=1 >> /conf/upgrade_log.txt 2>&1
203

    
204
	# Stream gzipped image to dd and explode image to new area
205
	echo "" >> /conf/upgrade_log.txt
206
	echo "/usr/bin/gzip -dc $IMG | /bin/dd of=/dev/${TOFLASH} obs=64k" >> /conf/upgrade_log.txt
207
	/usr/bin/gzip -dc $IMG | /bin/dd of=/dev/${TOFLASH} obs=64k >> /conf/upgrade_log.txt 2>&1
208

    
209
	# Grab an after upgrade look at fdisk
210
	echo "" >> /conf/fdisk_upgrade_log.txt
211
	echo "After upgrade fdisk/bsdlabel" >> /conf/upgrade_log.txt
212
	fdisk $BOOT_DRIVE >> /conf/fdisk_upgrade_log.txt
213
	bsdlabel -A ${BOOT_DRIVE}s1 >> /conf/fdisk_upgrade_log.txt
214
	bsdlabel -A ${BOOT_DRIVE}s2 >> /conf/fdisk_upgrade_log.txt
215
	bsdlabel -A ${BOOT_DRIVE}s3 >> /conf/fdisk_upgrade_log.txt
216
	echo "---------------------------------------------------------------" >> /conf/fdisk_upgrade_log.txt
217
	echo "" >> /conf/fdisk_upgrade_log.txt
218

    
219
	# Ensure that our new system is sound and bail if it is not and file a notice
220
	echo "" >> /conf/upgrade_log.txt
221
	echo "/sbin/fsck_ufs -y /dev/${COMPLETE_PATH}" >> /conf/upgrade_log.txt
222
	/sbin/fsck_ufs -y /dev/${COMPLETE_PATH} >> /conf/upgrade_log.txt 2>&1
223
	if [ $? != 0 ]; then
224
		file_notice "UpgradeFailure" "{\$g['product_name']} upgrade has failed.   Your system has been left in a usable state."
225
		rm -f $IMG
226
		rm -f /var/run/firmwarelock.dirty
227
		rm -f /var/run/firmware.lock
228
		/etc/rc.conf_mount_ro
229
		exit 1
230
	fi
231

    
232
	# Enable foot shooting
233
	sysctl kern.geom.debugflags=16
234

    
235
	# Add back the corresponding glabel
236
	echo "" >> /conf/upgrade_log.txt
237
	echo "/sbin/tunefs -L ${GLABEL_SLICE} /dev/${COMPLETE_PATH}" >> /conf/upgrade_log.txt
238
	/sbin/tunefs -L ${GLABEL_SLICE} /dev/${COMPLETE_PATH} >> /conf/upgrade_log.txt 2>&1
239

    
240
	# restore config
241
	cp -Rp /tmp/configbak/* /conf 2>/dev/null
242

    
243
	# Remove upgrade file
244
	rm -f $IMG
245

    
246
	# Mount newly prepared slice
247
	mkdir /tmp/$GLABEL_SLICE
248
	mount /dev/ufs/$GLABEL_SLICE /tmp/$GLABEL_SLICE
249

    
250
	# If /boot/loader.conf.local exists
251
	# copy to the other slice.
252
	if [ -f /boot/loader.conf.local ]; then
253
		cp /boot/loader.conf.local /tmp/$GLABEL_SLICE/boot/loader.conf.local
254
	fi
255

    
256
	# If /tmp/$GLABEL_SLICE/usr/local/share/pfSense/post_upgrade_command exists
257
	# after update then execute the command.
258
	echo "Checking for post_upgrade_command..." >> /conf/upgrade_log.txt
259
	if [ -f /tmp/$GLABEL_SLICE/usr/local/share/pfSense/post_upgrade_command ]; then
260
		echo "Found post_upgrade_command, executing ($GLABEL_SLICE)..." >> /conf/upgrade_log.txt
261
		sh /tmp/$GLABEL_SLICE/usr/local/share/pfSense/post_upgrade_command $GLABEL_SLICE >> /conf/upgrade_log.txt 2>&1
262
	fi
263

    
264
	# Update fstab
265
	cp /etc/fstab /tmp/$GLABEL_SLICE/etc/fstab
266
	sed -i "" "s/pfsense${OLD_UFS_ID}/pfsense${UFS_ID}/g" /tmp/$GLABEL_SLICE/etc/fstab
267
	if [ $? != 0 ]; then
268
		echo "Something went wrong when trying to update the fstab entry.  Aborting upgrade."
269
		file_notice "UpgradeFailure" "Something went wrong when trying to update the fstab entry.  Aborting upgrade."
270
		rm -f $IMG
271
		rm -f /var/run/firmwarelock.dirty
272
		rm -f /var/run/firmware.lock
273
		umount /tmp/$GLABEL_SLICE
274
		/etc/rc.conf_mount_ro
275
		exit 1
276
	fi
277
	echo "" >> /conf/upgrade_log.txt
278
	cat /tmp/$GLABEL_SLICE/etc/fstab >> /conf/upgrade_log.txt
279

    
280
	echo "" >> /conf/upgrade_log.txt
281
	find /tmp/$GLABEL_SLICE >/conf/file_upgrade_log.txt
282
	echo "" >> /conf/upgrade_log.txt
283

    
284
	# Unmount newly prepared slice
285
	umount /tmp/$GLABEL_SLICE
286

    
287
	sync
288

    
289
	# Set active mount slice in fdisk
290
	echo "" >> /conf/upgrade_log.txt
291
	echo "gpart set -a active -i ${SLICE} ${BOOT_DRIVE}" >> /conf/upgrade_log.txt
292
	gpart set -a active -i ${SLICE} ${BOOT_DRIVE} >> /conf/upgrade_log.txt 2>&1
293

    
294
	sync
295

    
296
	# Set active boot source - NanoBSD does not do this but otherwise we
297
	# end up with the wrong partition being active.
298
	echo "" >> /conf/upgrade_log.txt
299
	echo "/usr/sbin/boot0cfg -s ${SLICE} -v /dev/${BOOT_DRIVE}" >> /conf/upgrade_log.txt
300
	/usr/sbin/boot0cfg -s ${SLICE} -v /dev/${BOOT_DRIVE} >> /conf/upgrade_log.txt 2>&1
301

    
302
	# Disable foot shooting
303
	sysctl kern.geom.debugflags=0
304

    
305
	# Grab a final look at fdisk
306
	echo "" >> /conf/fdisk_upgrade_log.txt
307
	echo "Final upgrade fdisk/bsdlabel" >> /conf/fdisk_upgrade_log.txt
308
	fdisk $BOOT_DRIVE >> /conf/fdisk_upgrade_log.txt
309
	bsdlabel -A ${BOOT_DRIVE}s1 >> /conf/fdisk_upgrade_log.txt
310
	bsdlabel -A ${BOOT_DRIVE}s2 >> /conf/fdisk_upgrade_log.txt
311
	bsdlabel -A ${BOOT_DRIVE}s3 >> /conf/fdisk_upgrade_log.txt
312
	echo "---------------------------------------------------------------" >> /conf/fdisk_upgrade_log.txt
313
	echo "" >> /conf/fdisk_upgrade_log.txt
314

    
315
	# Remove extra stuff
316
	rm -rf /usr/savecore/*
317

    
318
	date >> /conf/upgrade_log.txt
319
	echo "" >> /conf/upgrade_log.txt
320

    
321
	# Trigger a package reinstallation on reboot
322
	touch /conf/needs_package_sync
323

    
324
	# remount /cf ro
325
	/etc/rc.conf_mount_ro
326
	/bin/sync
327

    
328
	echo "NanoBSD Firmware upgrade is complete.  Rebooting in 10 seconds." >> /conf/upgrade_log.txt 2>&1
329
	echo "NanoBSD Firmware upgrade is complete.  Rebooting in 10 seconds." | wall
330
	/etc/rc.notify_message -e -g -m "NanoBSD Firmware upgrade is complete.  Rebooting in 10 seconds."
331

    
332
	sleep 10
333

    
334
	rm -f /var/run/firmwarelock.dirty
335
	rm -f /var/run/firmware.lock
336
	. /etc/rc.reboot
337

    
338
	;;
339
pfSenseupgrade)
340

    
341
	# Sanity check - bail early if there's no firmware file!
342
	if [ ! -r $IMG ]; then
343
		echo "2nd parameter has not been passed or file does not exist. Exiting." >> /conf/upgrade_log.txt 2>&1
344
		/etc/rc.conf_mount_ro
345
		exit
346
	fi
347

    
348
	# wait 1 second before beginning
349
	sleep 1
350

    
351
	# Log that we are really doing a pfSense upgrade
352
	echo "" >> /conf/upgrade_log.txt
353
	echo "pfSenseupgrade upgrade starting" >> /conf/upgrade_log.txt
354
	echo "" >> /conf/upgrade_log.txt
355

    
356
	touch /var/run/firmwarelock.dirty
357

    
358
	if [ -f /tmp/perform_full_backup.txt ]; then
359
		echo "Performing full backup" >> /conf/upgrade_log.txt
360
		/etc/rc.create_full_backup
361
		rm /tmp/perform_full_backup.txt
362
	fi
363

    
364
	touch /conf/upgrade_log.txt
365
	echo "" >> /conf/upgrade_log.txt
366

    
367
	# Output environment information to log file
368
	output_env_to_log
369

    
370
	backup_chflags
371
	remove_chflags
372

    
373
	# Do we have a pre-upgrade hook in the update file?
374
	if [ `tar tvzf $IMG | grep /usr/local/share/pfSense/pre_upgrade_command | wc -l` -gt 0 ]; then
375
		tar xzvf $IMG -C / ./usr/local/share/pfSense/pre_upgrade_command >> /conf/upgrade_log.txt 2>&1
376
		chmod a+rx /usr/local/share/pfSense/pre_upgrade_command >> /conf/upgrade_log.txt 2>&1
377
		sh /usr/local/share/pfSense/pre_upgrade_command >> /conf/upgrade_log.txt 2>&1
378
	fi
379

    
380
	echo "Firmware upgrade in progress..." >> /conf/upgrade_log.txt 2>&1
381
	echo "Firmware upgrade in progress..." | wall
382
	/etc/rc.notify_message -e -g -m "Firmware upgrade in progress..."
383

    
384
	# backup config
385
	[ -d /tmp/configbak ] && rm -rf /tmp/configbak
386
	/bin/mkdir -p /tmp/configbak
387
	cp -Rp /conf/* /tmp/configbak 2>/dev/null
388

    
389
	# Remove logs from backup dir to avoid clobbering upon restore.
390
	rm /tmp/configbak/*_log.txt 2>/dev/null
391

    
392
	# tar explode image onto hd
393
	killall -9 check_reload_status
394
	killall -9 check_reload_status
395
	echo "Installing $IMG." >> /conf/upgrade_log.txt 2>&1
396
	cd / && /usr/bin/tar --exclude=./dev -xzUPf $IMG >> /conf/upgrade_log.txt 2>&1
397
	/usr/local/sbin/check_reload_status
398
	echo "Image installed $IMG." >> /conf/upgrade_log.txt 2>&1
399

    
400
	# process custom image if its passed
401
	if [ $# -eq 3 ]; then
402
		if [ -f $CUSTOMIMG ]; then
403
			echo "Custom image $CUSTOMIMG found." >> /conf/upgrade_log.txt 2>&1
404
			echo "Custom image ($CUSTOMIMG) found." >> /conf/upgrade_log.txt 2>&1
405
			PWD_DIR=`pwd`
406
			cd / && /usr/bin/tar xzPUf $CUSTOMIMG >> /conf/upgrade_log.txt 2>&1
407
			cd $PWD_DIR
408
			echo "Custom image $CUSTOMIMG installed." >> /conf/upgrade_log.txt 2>&1
409
		fi
410
	fi
411

    
412
	# restore config
413
	cp -Rp /tmp/configbak/* /conf 2>/dev/null
414

    
415
	# restore /etc symlinks
416
	rm /etc/hosts
417
	ln -s /var/etc/hosts /etc/hosts
418

    
419
	restore_chflags
420

    
421
	# Remove upgrade file
422
	rm -f $IMG
423

    
424
	if [ -e /etc/init_bootloader.sh ]; then
425
		if [ ! -x /etc/init_bootloader.sh ]; then
426
			chmod ug+x /etc/init_bootloader.sh
427
		fi
428
		/etc/init_bootloader.sh >> /conf/upgrade_log.txt 2>&1
429
	fi
430

    
431
	# Remove saved commit ID for gitsync
432
	rm -f /etc/version.gitsync
433

    
434
	# If /usr/local/share/pfSense/post_upgrade_command exists after update
435
	# then execute the command.
436
	if [ -f /usr/local/share/pfSense/post_upgrade_command ]; then
437
		if [ ! -x /usr/local/share/pfSense/post_upgrade_command ]; then
438
			chmod ug+x /usr/local/share/pfSense/post_upgrade_command
439
		fi
440
		/usr/local/share/pfSense/post_upgrade_command >> /conf/upgrade_log.txt 2>&1
441
	fi
442

    
443
	# remove unused files
444
	rm -rf /etc/rc.conf
445
	rm -rf /usr/savecore/*
446

    
447
	date >> /conf/upgrade_log.txt
448
	echo "" >> /conf/upgrade_log.txt
449

    
450
	# remount /cf ro
451
	/etc/rc.conf_mount_ro
452

    
453
	# release the firmware lock
454
	rm -f /var/run/firmwarelock.dirty
455
	rm -f /var/run/firmware.lock
456
	/bin/sync
457

    
458
	echo "Firmware upgrade is complete. Rebooting in 10 seconds." >> /conf/upgrade_log.txt 2>&1
459
	echo "Firmware upgrade is complete. Rebooting in 10 seconds." | wall
460
	/etc/rc.notify_message -e -g -m "Firmware upgrade is complete. Rebooting in 10 seconds."
461

    
462
	# Sleep and allow disks to catch up
463
	sleep 10
464

    
465
	# If the archive has unpacked a file called
466
	# /tmp/no_upgrade_reboot_required then do
467
	# not reboot after upgrade.
468
	if [ -f /tmp/no_upgrade_reboot_required ]; then
469
		rm /tmp/no_upgrade_reboot_required
470
	else
471
		. /etc/rc.reboot
472
	fi
473

    
474
	;;
475
esac
476

    
(53-53/105)