[OpenWrt-Devel] Generalising the boot process; Was Re: [PATCH V2] [boot] /init: allow, easier customisation of ramfs boot.

Stephen G. Parry sgparry at mainscreen.com
Wed Oct 15 10:32:29 EDT 2014

> Message: 7 Date: Mon, 13 Oct 2014 20:15:59 -0700 From: Florian
> Fainelli <florian at openwrt.org> To: John Crispin <blogic at openwrt.org>
> Cc: OpenWrt Development List <openwrt-devel at lists.openwrt.org>
> Subject: Re: [OpenWrt-Devel] [PATCH] [PATCH V2] [boot] /init: allow
> easier customisation of ramfs boot. Message-ID:
> <CAGVrzcbJPfZBk71czKON1Tf_tvaWXiEr5Xr2wgH59NA3-Hw_PQ at mail.gmail.com>
> Content-Type: text/plain; charset=UTF-8 2014-10-13 12:44 GMT-07:00
> John Crispin <blogic at openwrt.org>:
>> On 13/10/2014 00:03, Stephen Parry wrote:
>>> /init is the first pid 1 process in an initramfs environment. This fix adds
>>> lines to check for the existence of /bin/ramfsinit or /sbin/ramfsinit and exec
>>> if present. This allows packages to switch root early in the boot process. This
>>> will help support booting or kexecing from external storage and go some way
>>> toward fixing ticket #17465.
>> the ticket says extroot fails for !mtd. please elaborate on that. i
>> would rather we fix extroot to handle this use case rather than build a
>> way to bypass extroot
It already bypasses extroot. I agree extroot should be fixed, but that
it is quite involved for four reasons:

1. The extroot architecture currently relies heavily on pivot_root()
being able to 'swoop in' and do its stuff. Pivot_root is the only
mechanism that can move the root file system of any children of init
that have been forked prior to switch. There are a number of these.
Unfortunately pivot_root does not work for initramfs because it is not a
true mounted filesystem. It's just there.
2. There is a set of script hooks dedicated to ramfs boot inside the
current block, ubox or whatever it is this week architecture. However
all of this runs *outside* pid 1. This means you cannot safely or
effectively remount root i.e. currently they are useless.
3. The current code in a number of places the code goes looking for
"linux", "userdata" and "rootfs" mtd devices and assumes we booted from
or are intending to mount those - which can be disastrous. I am not sure
I can catch all the possible places this happens.
4. This part of the  boot up process is enormously complicated. I have a
UML process diagram of the whole thing I will finish at some point and
upload - it is not subtle. Changing it needs the input of those who
devised it. In my case all I want initramfs to do is remount the correct
root from external storage and run the proper init.

It will become more common for routers to have external or
multi-partition storage, leading to situations where you could have
several firmware installs on the same router e.g. for fallback after
external storage failure, experimentation, multi-stage boot etc. For
example my setup has a ramfs mini-kernel that loads from internal flash,
that then kexecs to a main kernel on external storage. It took a lot of
hacking to get it to work. (I had to do it via kexec cause my lousy
bootloader can't see external storage).

IMHO Any generalisation of the boot code should follow some kind of
principle where we do not assume the partition we booted from or are
going to use for root+userdata, preferably without any configuration
written into the kernel image, allowing general re-use within a given
router model. However, the only way I know of doing this requires
connivance from the bootloader (not possible) or kernel command line
hacks (ugly). NVRAM might do this for us, but this kind of goes against
the general openwrt design? It also means you could easily load the
wrong kernel for the wrong rootfs. However this seems the most promising
route currently. We could have NVRAM variables such as
"OPENWRT_USERDATA" and "OPENWRT_ROOTFS" which would override the normal
mtd scanning and direct the boot process to mount / pivot to those
filesystems instead.

> Agreed, should not we standardize on /linuxrc instead of ramfsinit,
> even though that is an initramfs, people might get confused even more
> with this custom script name.
The script version of init I have patched is only present in the ramfs
file system - AFAIK it it is not present other builds and is purely
there to set the INITRAMFS env var which then causes the main init to
short circuit the entire boot process, thus avoiding most of the code
that breaks in a !mtd build. So to call the custom scripts anything else
could be deemed confusing.
>>> Signed-off-by: Stephen Parry <sgparry at mainscreen.com>
>>> ---
>>> V2: Improved script structure using elif
>>> ---
>>>  target/linux/generic/base-files/init | 9 ++++++++-
>>>  1 file changed, 8 insertions(+), 1 deletion(-)
>>> diff --git a/target/linux/generic/base-files/init b/target/linux/generic/base-files/init
>>> index 514be57..e80b324 100755
>>> --- a/target/linux/generic/base-files/init
>>> +++ b/target/linux/generic/base-files/init
>>> @@ -1,4 +1,11 @@
>>>  #!/bin/sh
>>>  # Copyright (C) 2006 OpenWrt.org
>>>  export INITRAMFS=1
>>> -exec /sbin/init
>>> +
>>> +if [ -e /bin/ramfsinit ]; then
>>> +     exec /bin/ramfsinit
>>> +elif [ -e /sbin/ramfsinit ]; then
>>> +     exec /sbin/ramfsinit
>>> +else
>>> +     exec /sbin/init
>>> +fi
>> _______________________________________________
>> openwrt-devel mailing list
>> openwrt-devel at lists.openwrt.org
>> https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
> -- Florian
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org

More information about the openwrt-devel mailing list