This article attempts to state what the initscripts must and should do for the new init system being developed for OpenWrt. The goal is to deal with the race conditions that currently can occur, without losing current functionality.
On a Debian desktop system there is an analogue to preinit, which uses initramfs to bring up the system enough to the point init can operate. Unfortunately initramfs is not an option on openwrt because it wastes too much space. The binaries and scripts in an initramfs cannot be retained for use in the booted system, unless they are copied to RAM (tmpfs) (if anyone know otherwise and can point out how, please contact the devs), which is why preinit exists.
Preinit looks to linux like the final boot stage to init on the rootfs. Preinit then mounts the root file system, does pivot_root to the rootfs, and then use the real init to replace itself. Basically it transforms intself into the 'real' init and rootfs.
* Reduce preinit as much as possible so that init does most of the work * Maintain failsafe ability, so that if mounting, etc, rootfs fails, or init makes system inaccessible, that there is a way to get into the device and fix it. * Not start hotplug at all in preinit … for that matter no processes except the real init should cross the preinit/init boundary. * Be configurable…it should be possible to configure rootfs mount, init start and anything else that can happen after the jffs2 is mounted (and therefore a writable config is available) * LED and network message functionality should be available to switchinit (which runs a script to shutdown process and make some other process than the current init PID 1, e.g. for doing a safer sysupgrade, and firstboot ('factory reset')) * Support /opt type deployments as well as extroot (that is, extra packages on /opt rather than by replacing the jffs2 rootfs) * No open file descriptors/references on the old rootfs when init is executed on the target rootfs (this is why we don't just mount/pivot in init).
* JFFS2 Formatting must be done on a fully booted system, because on some routers (like the Fon with NOR flash), formatting takes a significant amount of time during which the router would be unavailable for use). That means preinit can't be where the formatting happens. * Ideally the firstboot script will take the router back to state exactly like after flashing without configuration saved), including the needs for formatting jffs2 * Restoring the configuration needs to be done after the rootfs is mounted, but before most configuration is used (most configuration is used in init or init-launched hotplug). * Saving the configuration should save the jffs2 (for squashfs)/or boot rootfs config not the config on external root. This is because the external root will still be available on the external storage after flashing, but the internal (jff2 or other boot rootfs) won't.
1. Allow failsafe 2. If initramfs, do initramfs, skip rest of this list 3. For Squashfs: Mount jffs2 (if already formatted) 4. For External Block: Mount swap (so fsck has enough memory)1) if present 5. For External Block: Mount rootfs (checking first if fsck available) or tmpfs (if no rootfs yet) 6. For External Block: Mount marked fses before init (e.g. for deployments where /opt contains packages/script that need to run early in init) 7. Start init or kexec
* Enable script output to serial before failsafe * emit UDP messages with progress of boot, or at the very least failsafe prompt * Network or Serial access
* LEDs indicator for hit button
* Button (on any button during failsafe window, enter failsafe)
* Setting LEDs requires sysfs (/sys) * OpenWrt LEDs depend on specific hardware as defined by /proc/cpuinfo, so /proc is needed * Obviously /dev is needed
* LED indicator for failsafe mode
* failsafe-related items *must not* rely on changing config, only on what is available in the flashed image.
check if jffs2 formatted if formatted, mount it in a temporary location combine boot rootfs and jffs2 (if present) kernel modules and swap/rootfs config mount should have /proc requires /dev
load modules needed for swap (if swap configured) (from rootfs or jffs2) run any swap-related scripts from either boot rootfs or jffs2 using swap-utils from either boot rootfs or jffs2 (if present) do swapon for configured swap needs swap-utils and blkid (for UUID based config) on bootfs or jffs2
load modules needed for rootfs (from rootfs or jffs2) run any rootfs-related scripts (e.g. for mmc) (e.g. mount usbfs) check filesystem for errors if fsck present on boot rootfs or jffs2 (depends on blkid) mount target rootfs (depends on blkid on boot rootfs or jffs2) pivot_root move any fs mounted on old root to new root
load modules needed by fses (if not previously loaded) run any associated scripts (.e.g for mmc/usbfs) (if not previously run) check filesystem for errors if fsck present on rootfs (depends on blkid) mount fs (depends on blkid)
For Init: Configurable PATH and environment variables Either do init or kexec a kernel on the rootfs or other previously mounted storage
Split /etc/init.d into independent chunks
Support betwork rootfs, perhaps by using switchinit with network kept up 1) Roughly 1 MB of RAM for every 1 GB of disk to successfully fsck the disk. Source.