summaryrefslogtreecommitdiff
blob: 19162b2e8200f08ab52ca2882fb307e07220524a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

#
# This script looks for a grub-entry=N kernel option
# (needs to be specified in /boot/grub/grub.conf by hand
# and for each kernel entry with the correct number)
# and calls grub-set-default with its value as argument.
# Used to update /boot/grub/default with the current
# running kernel entry for a convenient use of the grub
# fallback mechanism.
#
# Suggestion:
# Copy this script to /etc/init.d/grub-set-default,
# add it to the boot runlevel and use the following
# kernel options in grub.conf:
#
#   grub-entry=N panic=5 panic_on_oops=1
#
# WARNING:
# This script expects /boot to either reside on a separate volume
# and be mounted (readonly is ok), or to be part of the rootfs.
# It is however recommended to put /boot on a separate volume
# and mount it automatically but readonly, so System.map can
# be read but no files (kernel images etc.) can be damaged, removed
# or tampered with in any other way by accident.
#
# Direct feedback to Wolfram Schlich <wschlich@gentoo.org>.
#

depend() {
	need localmount
}

start() {

	# check for /proc stuff
	if [[ ! -e /proc/cmdline || ! -e /proc/mounts ]]; then
		eerror "/proc does not appear to be mounted, cannot set grub default entry"
		eend 1
		return 1
	fi

	# grub.conf entry number to be set as default
	declare -i grub_entry=-1

	# is /boot on a separate volume and mounted read-only?
	declare -i boot_ro=0

	# split kernel command line into positional arguments
	IFS=' '
	set -- $(</proc/cmdline)
	unset IFS

	# loop through kernel command line
	while [[ ${#@} -gt 0 && ${grub_entry} -eq -1 ]]; do
		case "${1}" in
			grub-entry=*)
				grub_entry=${1##*=}
				;;
			*)
				;;
		esac
		shift
	done

	# be done if no grub-entry= option was passed to the kernel
	if [ ${grub_entry} -eq -1 ]; then
		einfo "Skipping setting grub default entry"
		return 0
	fi

	# split /proc/mounts into array by newline
	IFS=$'\n'
	mounts=(
		$(</proc/mounts)
	)
	unset IFS

	# loop through array of mounts
	for mount in "${mounts[@]}"; do

		# split mount line into fields
		IFS=' '
		set -- ${mount}
		unset IFS
		mount_point="${2}" # field #2
		mount_opts="${4}" # field #4
		#einfo "Mount point: ${mount_point}"
		#einfo "Mount opts: ${mount_opts}"
		case "${mount_point}" in
			/boot)
				#einfo "Mount point /boot is on a separate volume"
				IFS=','
				set -- ${mount_opts}
				unset IFS
				while [[ ${#@} -gt 0 ]]; do
					case "${1}" in
						ro)
							boot_ro=1
							;;
						*)
							;;
					esac
					shift
				done
				;;
			*)
				;;
		esac
	done

	# remount /boot rw if needed
	if [ ${boot_ro} -eq 1 ]; then
		#einfo "Mount point /boot needs remounting -> rw"
		if ! /bin/mount -o remount,rw /boot; then
			eerror "Failed to remount /boot rw"
			eend 1
			return 1
		fi
	fi

	# call grub-set-default
	ebegin "Setting grub default entry to current entry ${grub_entry}"
	/sbin/grub-set-default ${grub_entry}
	eend ${?}

	# remount /boot ro if needed
	if [ ${boot_ro} -eq 1 ]; then
		#einfo "Mount point /boot needs remounting -> ro"
		if ! /bin/mount -o remount,ro /boot; then
			eerror "Failed to remount /boot ro"
			eend 1
			return 1
		fi
	fi

}