Package: kexec-tools
Version: 1:2.0.0-1
Severity: wishlist
Tags: patch

Hello,

It would be nice if the kexec-load init script could parse
/boot/grub/menu.lst to determine the kernel, command-line, and initrd to
load.  On systems that use grub, this is more canonical than the
/vmlinuz and /initrd.img links; plus, getting the command-line from
grub's configuration makes the default behavior of "reboot" with
kexec-tools installed more predictable.  (Right now, if I change an
append option in menu.lst, I have to remember either to use "reboot -f"
or manually load the kernel with a new --append option.)

The attached patch implements this if there is a "USE_GRUB_CONFIG=true"
line in /etc/default/kexec.  If /boot/grub/menu.lst doesn't exist, it
falls back to the previous behavior.

Thanks for considering the patch.

-- 
John Wright <j...@debian.org>
diff --git a/debian/kexec-load.init.d b/debian/kexec-load.init.d
index 0312265..f2949ad 100644
--- a/debian/kexec-load.init.d
+++ b/debian/kexec-load.init.d
@@ -16,11 +16,63 @@ PATH=/usr/sbin:/usr/bin:/sbin:/bin
 
 test -r /etc/default/kexec && . /etc/default/kexec
 
+process_grub_entry() {
+	if awk '{print $2}' /proc/mounts | grep -q '^/boot$'; then
+		BOOT="/boot"
+	else
+		BOOT=
+	fi
+
+	echo INITRD=
+	while read command args; do
+		if [ "$command" = "kernel" ]; then
+			echo "$args" | while read kernel append; do
+			echo KERNEL_IMAGE=\"${BOOT}${kernel}\"
+			echo APPEND=\"${append}\"
+		done
+	elif [ "$command" = "initrd" ]; then
+		echo INITRD=\"${BOOT}${args}\"
+	fi
+done
+}
+
+get_grub_kernel() {
+	test -f /boot/grub/menu.list || return
+	data=$(cat /boot/grub/menu.lst)
+
+	default=$(echo "$data" | awk '/^default/ {print $2}')
+	if [ -z "$default" ]; then
+		default=0
+	elif [ "$default" = "saved" ]; then
+		default=$(cat /boot/grub/default | grep -v ^#)
+	fi
+	start_offset=$((default + 1))
+	end_offset=$((default + 2))
+
+	# grub entries start with "title" commands.  Get the line numbers that
+	# surround the first entry.
+	offsets=$(echo "$data" | grep -n ^title | cut -d: -f1)
+	begin=$(echo "$offsets" | tail -n+$start_offset | head -n1)
+	end=$(echo "$offsets" | tail -n+$end_offset | head -n1)
+
+	# If this is the last entry, we need to read to the end of the file
+	if [ -z "$end" ]; then
+		numlines=$(echo "$data" | wc -l)
+		end=$((numlines + 1))
+	fi
+
+	length=$((end - begin))
+	entry=$(echo "$data" | tail -n+$begin | head -n$length)
+	eval $(echo "$entry" | process_grub_entry)
+}
+
 do_stop () {
 	test "$LOAD_KEXEC" = "true" || exit 0
 	test -x /sbin/kexec || exit 0
 	test "x`cat /sys/kernel/kexec_loaded`y" = "x1y" && exit 0
 
+	test "$USE_GRUB_CONFIG" = "true" && get_grub_kernel
+
 	REAL_APPEND="$APPEND"
 
 	test -z "$REAL_APPEND" && REAL_APPEND="`cat /proc/cmdline`"
diff --git a/debian/kexec-tools.postinst b/debian/kexec-tools.postinst
index fbd44e4..cce4116 100644
--- a/debian/kexec-tools.postinst
+++ b/debian/kexec-tools.postinst
@@ -71,6 +71,11 @@ umask 022
 # Load a kexec kernel (true/false)
 LOAD_KEXEC=true
 
+# If USE_GRUB_CONFIG is true, and /boot/grub/menu.lst exists, kexec-load use it
+# to determine the kernel to load.  Otherwise it will fall back to the options
+# below.
+USE_GRUB_CONFIG=false
+
 # Kernel and initrd image
 KERNEL_IMAGE="/vmlinuz"
 INITRD="/initrd.img"
diff --git a/debian/kexec.default b/debian/kexec.default
index 025637e..628d67b 100644
--- a/debian/kexec.default
+++ b/debian/kexec.default
@@ -4,6 +4,11 @@
 # Load a kexec kernel (true/false)
 LOAD_KEXEC=true
 
+# If USE_GRUB_CONFIG is true, and /boot/grub/menu.lst exists, kexec-load use it
+# to determine the kernel to load.  Otherwise it will fall back to the options
+# below.
+USE_GRUB_CONFIG=false
+
 # Kernel and initrd image
 KERNEL_IMAGE="/vmlinuz"
 INITRD="/initrd.img"

Reply via email to