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

Reply via email to