The following patch creates a new package block-extroot-kexec which boots a new
kernel off USB storage during the boot process
from internal flash. While the package block-extroot allows an external root
filesystem to be used, it still has to
boot the kernel on the internal flash. This package allows booting the device
from a different kernel to that on the flash, allowing
amongst other things, testing of new kernels without risking bricking the
router.
The package depends on block-extroot to mount the USB device, but then loads
and boots the new kernel prior to the pivot_root that
uses the /overlay filesystem on the USB device.
If is configured though a standard UCI script, /etc/config/kexec, which has 4
options:
config file reboot
option enabled 1
option filename boot/linux-2.6.32.10.elf
option params "vga=386 p2=2"
option add_params "vga=683 p1=1"
enabled - if not set, then the kexec will not be done
fileame - the path of the kernel image relative to the /overlay mount point.
params - this option is passed as the parameter --command-line= to the kexec
-l command
add_params - additional parameters, passed as the parameter --append= to the
kexec -l command.
The script first searches for the kexec configuration file in
/overlay/etc/config (i.e. /etc/config on the USB device), and if that
does not exist then on /tmp/overlay/etc/config (i.e. the internal jffs2
filesystem), and finally on /etc/config (the internal
squashfs filesystem).
The package needs to be built into the base flash filesystem, like
block-extroot. Selecting the package selects kexec-tools. Ticket
#7114 has a patch that makes selecting kexec-tools also add the kernel
configuration for building kexec support into the kernel.
Otherwise kexec has to be manually configured into the kernel.
To build the kernel to be placed on the USB device, in make menuconfig the
ramdisk option in Target Images has to be selected. I also
select LZMA compression, otherwise the image is too large for kexec to load.
The etc/preinit script has to be changed to identify the
rootfs. The package preinit-rootfs does this (again has to be included in the
base filesystem, i.e. option <M> does not work), and
allows configuration of the rootfs device. This package is only available if a
ramdisk target image has been selected.
This has been extensively tested on a WL500GPv1 with kernel 2.6.32.10, but also
needs the patch included in ticket #7115
for kexec to work on mips processors (included in Changeset 20745).
This package was inspired by the topic at
https://forum.openwrt.org/viewtopic.php?id=23901 .
Signed-off-by: Quentin Armitage <[email protected]>
Index: package/block-extroot-kexec/files/51_kexec_reboot
===================================================================
--- package/block-extroot-kexec/files/51_kexec_reboot (revision 0)
+++ package/block-extroot-kexec/files/51_kexec_reboot (revision 0)
@@ -0,0 +1,78 @@
+#!/bin/sh
+# Copyright (C) 2010 OpenWrt.org
+
+# This is free software, licensed under the GNU General Public License v2.
+#
+# /etc/config/kexec configures this script. It requires that the extroot mount
+# was successful, and uses /overlay that it mounted.
+#
+#Example config:
+#config file reboot
+# option enabled 1
+# option filename linux.elf
+# option params "vga=386 p2=2"
+# option add_params "vga=683 p1=1"
+#
+# This will execute:
+# kexec -l /overlay/linux.elf --command_line="vga=386 p2=2"
--append="vga=683 p1=1" && kexec -e
+
+. /etc/functions.sh
+. /lib/functions/extmount.sh
+
+# Determine if we are requested to do a kexec reboot
+
+config_kexec() {
+ local cfg="$1"
+
+ config_get_bool kexec_enabled "$cfg" enabled 0
+ config_get kexec_filename "$cfg" filename
+ config_get kexec_params "$cfg" params
+ config_get kexec_add_params "$cfg" add_params
+}
+
+check_and_do_kexec() {
+ local OLD_UCI_CONFIG_DIR="$UCI_CONFIG_DIR"
+
+ # If already doing a kexec boot, don't reboot.
+ # See description of root_device in /lib/preinit/50_determine_usb_root
+ determine_root_device
+ [ "$root_device" = "/dev/root" ] || return 0
+
+ [ "$pi_extroot_mount_success" = "true" ] || return 0
+
+ # If the extroot (mounted on /overlay) has a config, use it, otherwise
+ # try jffs2 overlay
+ if [ -r "/overlay/etc/config/kexec" ]; then
+ UCI_CONFIG_DIR=/overlay/etc/config
+ elif [ "$jffs" = "/tmp/overlay" ] && [ -r
"/tmp/overlay/etc/config/kexec" ]; then
+ UCI_CONFIG_DIR=/tmp/overlay/etc/config
+ fi
+
+ if [ -r "$UCI_CONFIG_DIR/kexec" ]; then
+ config_load kexec
+ config_foreach config_kexec file
+
+ if [ "$kexec_enabled" = "1" ]; then
+ if [ ! -f /overlay/$kexec_filename ] ; then
+ echo "kexec image $kexec_filename missing:
continuing with existing boot"
+ else
+ kexec_cl=
+ kexec_ap=
+ [ -n "$kexec_params" ] &&
kexec_cl="--command_line=\"$kexec_params\""
+ [ -n "$kexec_add_params" ] &&
kexec_ap="--append=\"$kexec_add_params\""
+ kexec -l /overlay/$kexec_filename $kexec_opt
"$kexec_cl" "$kexec_ap"
+ if [ $? -ne 0 ]; then
+ echo "kexec -l failed: continuing with
existing boot"
+ else
+ echo kexec\'ing $kexec_filename
+ kexec -e
+ echo "kexec -e failed: continuing with
existing boot"
+ fi
+ fi
+ fi
+ fi
+
+ UCI_CONFIG_DIR="$OLD_UCI_CONFIG_DIR"
+}
+
+boot_hook_add preinit_mount_root check_and_do_kexec
Index: package/block-extroot-kexec/Makefile
===================================================================
--- package/block-extroot-kexec/Makefile (revision 0)
+++ package/block-extroot-kexec/Makefile (revision 0)
@@ -0,0 +1,52 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=block-extroot-kexec
+PKG_VERSION:=0.0.1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/block-extroot-kexec/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=kernel on secondary storage
+ SUBMENU:=disc
+endef
+
+define Package/block-extroot-kexec
+ $(call Package/block-extroot-kexec/Default)
+ MENU:=1
+ DEPENDS:=+block-extroot +kexec-tools
+endef
+
+define Package/block-extroot-kexec/description
+ Based on the moduluarized preinit and firstboot, adds the option to have
+ the kernel on storage other than the jffs or the boot root device.
+ For a squashfs image this package must be installed into the image, not as
+ a package to add later.
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+define Package/block-extroot-kexec/install
+ $(INSTALL_DIR) $(1)/lib/preinit
+ $(INSTALL_DATA) ./files/51_kexec_reboot $(1)/lib/preinit/
+endef
+
+$(eval $(call BuildPackage,block-extroot-kexec))
+
Index: package/preinit-rootfs/Config.in
===================================================================
--- package/preinit-rootfs/Config.in (revision 0)
+++ package/preinit-rootfs/Config.in (revision 0)
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+#
+
+menuconfig PREINIT_EXTERNAL_ROOTFS
+ string
+ prompt "External rootfs device" if PACKAGE_preinit-rootfs
+ default "/dev/sda1"
+ help
+ This is the device on which the root filesystem resides used
+ by a kernel kexec'd from external storage.
+
Index: package/preinit-rootfs/Makefile
===================================================================
--- package/preinit-rootfs/Makefile (revision 0)
+++ package/preinit-rootfs/Makefile (revision 0)
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2010 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=preinit-rootfs
+PKG_VERSION:=0.0.1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/preinit-rootfs/Default
+ SECTION:=utils
+ CATEGORY:=Utilities
+ TITLE:=Specify rootfs for kexec'd boot
+ SUBMENU:=disc
+endef
+
+define Package/preinit-rootfs
+ $(call Package/preinit-rootfs/Default)
+ MENU:=1
+ DEPENDS:=...@target_rootfs_initramfs
+endef
+
+define Package/preinit-rootfs/config
+ source "$(SOURCE)/Config.in"
+endef
+
+define Package/preinit-rootfs/description
+ Specified the root filesystem device for a kernel kexec'd off external
+ storage.
+endef
+
+define Build/Prepare
+endef
+
+define Build/Configure
+endef
+
+define Build/Compile
+endef
+
+ifneq ($(CONFIG_PREINIT_EXTERNAL_ROOTFS),)
+ define Package/preinit-rootfs/install
+ $(INSTALL_DIR) $(1)/etc
+ echo "rootfs=\"$(CONFIG_PREINIT_EXTERNAL_ROOTFS)\""
>$(1)/etc/preinit.rootfs
+ endef
+endif
+
+$(eval $(call BuildPackage,preinit-rootfs))
+
Index: package/base-files/files/etc/preinit
===================================================================
--- package/base-files/files/etc/preinit (revision 20584)
+++ package/base-files/files/etc/preinit (working copy)
@@ -5,6 +5,8 @@
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
. /etc/diag.sh
+[ -f /etc/preinit.rootfs ] && . /etc/preinit.rootfs
+
preinit_essential_hook=
preinit_main_hook=
failsafe_hook=
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel