User Tools

Site Tools


doc:techref:preinit_mount

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
doc:techref:preinit_mount [2013/07/10 03:44]
elecnix rephrase
doc:techref:preinit_mount [2016/01/27 19:32] (current)
maga [preinit_essentials]
Line 1: Line 1:
 +======= Preinit and Root Mount and Firstboot Scripts =======
  
 +See [[doc:​howto:​extroot|Rootfs on External Storage]] for information on external rootfs mounting.
 +
 +====== Abstract ======
 +
 +This document presents the preinit / firstboot boot sequence. The boot system is extensible via (new) packages such as rootfs on usb, or 
 +enhanced failsafe.
 +
 +We describe the portion of the OpenWrt boot sequence that occurs before the '​init'​ program is executed (when booting in multiuser mode), as well as the script that is responsible for creating and initializing the root filesystem on the first boot after flashing the device with OpenWrt.
 +
 +====== Context: ​ Boot Sequence ======
 +
 +The basic OpenWrt boot sequence is:
 +
 +  - boot loader loads kernel
 +  - kernel loads whilst scaning the mtd partition //rootfs// for a valid superblock for mounting the SquashFS partition (which contains /etc). More info at [[doc/​techref/​filesystems#​technical.details]]
 +  - kernel calls ''/​etc/​preinit''​ (the kernel considers this to be the ''​init''​ (or root) process
 +  - ''/​etc/​preinit''​ prepares system for multiuser mode
 +  - ''/​etc/​preinit''​ ''​exec''​s ''/​sbin/​init''​ which becomes the ''​init''​ (or root) process and launches multiuser
 +  - ''/​sbin/​init''​ launches processes according to /​etc/​inittab. ​
 +  - Typically the first process launched is ''/​etc/​init.d/​rcS''​ which causes the scripts in ''/​etc/​rc.d''​ which begin with '​S'​ to be launched (in glob sort order). The ''/​etc/​rc.d''​ directory is populated with symlinks to the scripts in ''/​etc/​init.d''​. Each script in ''/​etc/​init.d''​ accepts ''​enable''​ and ''​disable''​ arguments for creating and removing the symlinks.
 +  - These script initialize the system and also initialize daemons that wait for input, so that when all the scripts have executed the normal system is active. ​ On first boot this initializing includes the process of preparing the root filesystem for use.
 +
 +----
 +
 +====== Overview ======
 +
 +===== Preinit =====
 +
 +Preinit brings the system from raw kernel to ready for multiuser. ​ To do so
 +it performs the following tasks:
 +
 +  - Sources "/​etc/​functions.sh"​ and ''/​lib/​functions/​boot.sh''​ for common functions for boot/mount
 +  - Mounts essential kernel filesystems like procfs
 +  - Initializes device tree (/​dev) ​
 +  - Initializes console (serial console if present, otherwise dummy so that the script interpreter works properly)
 +  - Presents opportunity for the user to enter a special operating mode called **'​failsafe'​** (Failsafe mode is presented in a separate section. ​ Once failsafe ​ mode is entered it doesn'​t exit.  A reboot is necessary to enter normal ​ operating mode).
 +  - **Mounts the root filesystem** (this involves a number steps, presented in  a separate section)
 +  - If it's the first time booting after flashing the firmware, and a previous configuration was saved during the flashing process, that configuration is restored.
 +  - Becomes (though ''​exec''​) '​init'​ which goes to multiuser mode
 +
 +===== Failsafe =====
 +
 +The //root file system// is actually an overlay which can be consisted of a read-only SquashFS file system (mounted at ''/​rom''​) and a writable JFFS2 partition (mounted under ''/​overlay''​). In Failsafe mode only the squashfs FS will be mounted (changes made to jffs2 partitons will be ignored), plus the following steps:
 +
 +  - Prepares network interface (optional) and notifies that failsafe mode is being entered
 +  - Launches daemon to allow network logins
 +  - Allows login via serial console, if there is one.
 +  - When the serial console login process exits, failsafe doesn'​t exit, instead it continues to wait for network logins (whether or not they are actually possible).
 +
 +
 +===== Mount Root Filesystem =====
 +
 +all_jffs2 refers to a '​jffs2'​ target in menuconfig; e.g. firmware has
 +no squashfs, but is purely a rw filesystem (jffs2), while, jffs2 in
 +the following text refers to the jffs2 portion of a [[doc:​techref:​filesystems#​overlayfs|squashfs/​jffs2]] system.
 +
 +  - Kernel has previously mounted squashfs partition by scanning the mtd partition ''​rootfs''​ for a valid superblock (see step 2 of [[doc/​techref/​preinit_mount#​contextboot.sequencel]]) FIXME **Make sure it's correct**
 +  - If there is no mtd device with label ''​rootfs_data'',​ then mounts ''/​dev/​root''​ (e.g. squashfs or all_jffs2 with no squashfs) as root filesystem, and indicates that further steps should be skipped
 +  - If mtd device ''​rootfs_data''​ has not already been formatted, mounts a tmpfs (ramdisk) as root filesystem, and indicates that further steps should be skipped.
 +  - Mounts previously formatted jffs2 partition on ''/​overlay''​ and indicates successful mount.
 +  - Makes successfully mounted ''/​overlay''​ (if it exists) the new root filesystem and moves previous root filesystem to ''/​rom'',​ and indicates to skip further steps.
 +  - This is only reached on an error condition; attempts to mount a tmpfs (ramdisk) as root filesystem
 +  - This is only reached if no other step succeeds; attempt to mount ''/​dev/​root''​ (e.g. squashfs/​all_jffs2) as root filesystem.
 +
 +** * ** ''/​overlay''​ was previously named ''/​jffs2''​
 +
 +===== First Boot =====
 +
 +''/​sbin/​firstboot''​ may be referenced in three ways.  ​
 +
 +  * It may be called as part of the system startup, in which cased it is called as ''/​sbin/​firstboot switch2jffs''​.  ​
 +  * It may be used as a standalone command with no parameters (.e.g. ''/​sbin/​firstboot''​)
 +  * It may be sourced from another script
 +
 +==== Common ====
 +
 +  - Source ''/​lib/​functions/​boot.sh''​ for common functions (e.g. also used by preinit)
 +  - Source files used by hooks
 +  - Determine how called, and branch to appropriate commands.
 +
 +==== Sourced rather than executed ====
 +
 +  - Determine (and set variable for) MTD rootfs_data partition
 +  - Determine (and set variable for) rom partition
 +  - Determine (and set variable for) jffs2 partition
 +
 +==== Executed with no parameters ====
 +
 +  * Resets jffs2 to original settings, if possible.
 +  * If jffs2 is not mounted, erases mtd and attempts format, mount, and pivot jffs2 as root.
 +
 +If jffs2 is mounted, ''​firstboot''​ runs hook ''​jffs2reset''​
 +
 +  - Determine (and set variable for) MTD rootfs_data partition
 +  - Determine (and set variable for) rom partition
 +  - Determine (and set variable for) jffs2 partition
 +  - Determine (and set variable to indicate) whether the mini overlay filesystem type is supported.
 +  - If overlay is supported, remove all files on jffs2 and remount it.
 +  - If overlay not supported, create directories and symlinks, copying only certain critical files 
 +
 +  * Note: since r35712 the firstboot script requires an inputted '​y'​ as confirmation. If using firstboot in a reset button script, you need to get that y inputted, e.g. by using the yes command: ​ yes | firstboot
 +
 +==== Executed with parameter '​switch2jffs'​ ====
 +
 +  - Determine (and set variable for) MTD rootfs_data partition
 +  - Determine (and set variable for) rom partition
 +  - Determine (and set variable for) jffs2 partition
 +  - Determine if mini overlay is supported. ​ If not run hook no_fo
 +  - Otherwise, if mounted, skip the rest, otherwise mount under squashfs (''/​rom/​jffs''​)
 +  - Copy ramdisk to jffs2
 +  - Move ''/​jffs''​ to ''/''​ (root) and move ''/''​ (root) to ''/​rom''​
 +  - Cleanup
 +
 +
 +==== hook no_fo ====
 +
 +  - Switch to kernel fs, get rid of union overlay and bind from /tmp/root
 +  - Mount jffs (and make it safe for union)
 +  - If not mounted, mount; copy from squashfs, and pivot so that /jffs is now / (root)
 +  - Copy files from ramdisk
 +  - Get rid of unnecessary mounts (cleanup)
 +
 +
 +====== Preinit Operation ======
 +
 +Preinit consists of a number of scripts. ​ The main script is ''/​etc/​preinit''​
 +which reads in the scripts. ​ The scripts define functions which they attach to
 +hooks. ​ These hooks are, when processed, launching the functions in the order they
 +were added to the hooks.
 +
 +Currently there are five hooks used by the preinit system:
 +
 +  * ''​preinit_essential''​
 +  * ''​preinit_main''​
 +  * ''​failsafe''​
 +  * ''​initramfs''​
 +  * ''​preinit_mount_root''​
 +
 +Each hook have a corresponding string variable containing the name of each function to
 +be executed, separated by spaces. ​ The hook variables have ''​_hook''​ appended to
 +the hook name.  Thus the name of the variable for the ''​preinit_essential''​ hook
 +is ''​preinit_essential_hook''​.
 +
 +===== Main Preinit Script =====
 +
 +The main preinit script is actually quite empty. It:
 +
 +  - Initializes some variables (including the hook variables)
 +  - Defines the function ''​pi_hook_add'',​ which is used to add functions to a hook
 +  - Defines the function ''​pi_run_hook'',​ which executes the functions that were added to a hook
 +  - Sources (reads) the shell scripts under folder ''/​lib/​preinit/'',​ in glob sort order
 +  - Processes the hook ''​preinit_essential''​
 +  - Initializes variables used by ''​preinit_main''​
 +  - Processes the hook ''​preinit_main''​
 +
 +That's it.
 +
 +===== Variables =====
 +
 +There are a number of variables that control options of preinit. ​ Defaults are
 +defined in the main script ''/​etc/​preinit''​ defined by the ''​base-files''​ package.
 +However the variables are customizable via ''​make menuconfig'',​ in section ​
 +"​Preinit configuration options"​. The OpenWrt build process will then create ​
 +the file ''/​lib/​preinit/​00_preinit.conf''​ which will be sourced by the main 
 +script.
 +
 +The variables defined at present are:
 +
 +^ Variable ​          ^ Description ​                                            ^
 +|''​pi_ifname'' ​       | The device name of the network interface used to emit network messages during preinit (except failsafe) ​                                |
 +|''​pi_ip'' ​           | The IP address of the preinit network (see above) ​      |
 +|''​pi_broadcast'' ​    | The broadcast address of the preinit network (see above)|
 +|''​pi_netmask'' ​       | The netmask for the preinit network (see above) ​       |
 +|''​fs_failsafe_wait_timeout''​| How long to pause while allowing the user to choose to enter failsafe mode.  Default is two (2) seconds. ​                      |
 +|''​pi_suppress_stderr''​| If this is "​y",​ then output on standard error (stderr, file descriptor 2), is ignored during preinit. ​ This is the default in previous versions of OpenWrt (which did not have this option) ​                          |
 +|''​pi_init_suppress_stderr''​| If ''​pi_suppress_stderr''​ is not "​y"​ (i.e. stderr is not suppressed for preinit), then this option controls whether init, and process run by init, except those associated with a terminal device (e.g. ''​tts/​0'',​ ''​ttyS0'',​ ''​tty1'',​ ''​pts/​0'',​ or other similar devices) will have stderr suppressed (not that network terminals such as those from SSH are associated with a pseudo-terminal device such as ''​pty0/​pty1''​ and are thus unaffected). ​ As with ''​pi_suppress_stderr'',​ the default, and behaviour from previous versions of  OpenWrt is "​y"​. ​     |
 +|''​pi_init_path'' ​     | The default search PATH for binaries for commands run by init.  Default is ''/​bin:/​sbin:/​usr/​bin:/​usr/​sbin'' ​                           |
 +|''​pi_init_cmd'' ​      | The command to run as ''​init''​. ​ Default is ''/​sbin/​init''​|
 +|''​pi_preinit_no_failsafe_netmsg''​ | suppress netmsg to say that one can enter failsafe mode |
 +|''​pi_preinit_net_messages''​ | If enabled, show more network messages than just the message that one can enter failsafe mode |
 +
 +There are also variables used in the operation of preinit. ​ They are:
 +
 +^ Variable ​            ^ Description ​                                                                   ^
 +|''​preinit_essential_hook''​| Variable containing hook names to execute, in order, for hook ''​preinit_essential''​|
 +|''​preinit_main_hook'' ​    | Ditto, for ''​preinit_main'' ​                                                       |
 +|''​failsafe_hook'' ​        | Ditto, for ''​failsafe'' ​                                                           |
 +|''​initramfs_hook'' ​       | Ditto, for ''​initramfs'' ​                                                          |
 +|''​preinit_mount_root_hook''​| Ditto, for ''​preinit_mount_root'' ​                                                |
 +|''​pi_mount_skip_next'' ​   | During hook ''​preinit_mount_root'',​ skips most steps; usually set by a preceeding step |
 +|''​pi_jffs2_mount_success''​| During hook ''​preinit_mount_root'',​ used by steps following mount attempt to determine which action they should take |
 +
 +===== Hooks =====
 +
 +The following sections describe the files and functions used by the various ​
 +hooks.
 +
 +**NB**: The files, even though divided by hook here are all in the single
 +''/​lib/​preinit''​ directory, and are thus combined in the directory lists, and
 +are processed in glob sort order, not by hook (when sourcing them, the hooks
 +specify the order of the execution of functions, which is as listed below)
 +
 +
 +==== Development ==== 
 +For the purposes of development,​ you will locate the files under ''​$ROOTDIR/​package/​base-files/​files/​lib/​preinit'',​ for the existing files, and you can add new files anywhere that ultimately ends up in ''/​lib/​preinit''​ on the router (while in preinit, e.g. not by user edits after read-write is mounted).
 +
 +==== preinit_essentials ====
 +
 +:!: With the introduction of [[doc:​techref:​procd|procd]],​ effective in Chaos Calmer release, the tasks of this hook are done in c code and at least on some images (verified on a BRCM63xx one) this hook is unused.
 +
 +The preinit_essentials hook takes care of mounting essential kernel
 +filesystems such as proc, and initializing the console.
 +
 +Files containing the functions executed by this hook
 +
 +^ File                ^ Functions ​                                             ^
 +|10_essential_fs ​   | do_mount_procfs,​ do_mount_sysfs,​ do_mount_tmpfs ​ |
 +|20_device_fs_mount| do_mount_devfs,​ do_mount_hotplug,​ do_mount_udev,​ choose_device_fs ​                                                             |
 +|30_device_daemons ​ | init_hotplug,​ init_udev, init_device_fs ​           |
 +|40_init_shm ​       | init_shm ​                                             |
 +|40_pts_mount ​      | do_mount_pts ​                                        |
 +|50_choose_console ​ | choose_console ​                                       |
 +|60_init_console ​   | init_console ​                                         |
 +
 +Functions, in order, executed by this hook (doesn'​t list the functions only
 +called by other functions)
 +
 +^Function ​           ^ Description ​                                            ^
 +|do_mount_procfs ​  | mounts /proc                                            |
 +|do_mount_sysfs ​   | mounts /sys                                             |
 +|do_mount_tmpfs ​   | mounts /tmp                                             |
 +|choose_device_fs ​ | determines type of device daemon and the appropriate filesystem to mount on /dev for that device daemon ​                            |
 +|init_device_fs ​   | launches daemons (if any) responsible for population /dev, and/or creating hotplug events when devices are added/​removed (and for initial coldplug events) ​                                                         |
 +|init_shm ​         | makes sure /dev/shm exists ​                              |
 +|init_pts ​         | makes sure /dev/pts exists ​                              |
 +|do_mount_pts ​    | mounts devpts on /dev/pts (pseudo-terminals) ​            |
 +|choose_console ​   | determines devices for stdin, stdout, and stderr ​        |
 +|init_console ​     | activates stdin, stdout, and stderr of preinit (and  subsequent init) (prior to this they are not present in the environment) ​           |
 +
 +Functions which are called by other functions, rather than directly as part of a hook
 +
 +^Function ​           ^ Description ​                                            ^
 +| do_mount_devfs ​    | mount devfs on /dev                                     |
 +| do_mount_hotplug ​  | mount tmpfs on /dev (for hotplug) ​                      |
 +| do_mount_udev ​     | mount tmpfs on /dev (for udev)                          |
 +| init_hotplug ​      | set hotplug handler (actually initiated after console ​ init) |
 +| init_udev ​         | start udev                                              |
 +
 +==== preinit_main ====
 +
 +The //​preinit_main//​ hook performs all the functions required of preinit,
 +except those functions, like console, that are essential even for preinit ​
 +tasks.
 +
 +^File                         ^ Description ​                                   ^
 +|10_indicate_preinit ​       | preinit_ip, preinit_ip_deconfig,​ preinit_net_echo,​ preinit_echo,​ pi_indicate_led,​ pi_indicate_preinit ​               |
 +|30_failsafe_wait ​          | fs_wait_for_key,​ failsafe_wait ​            |
 +|40_run_failsafe_hook ​     | run_failsafe_hook ​                           |
 +|50_indicate_regular_preinit| indicate_regular_preinit_boot ​          |
 +|60_init_hotplug ​           | init_hotplug ​                                 |
 +|70_initramfs_test ​         | initramfs_test ​                               |
 +|80_mount_root ​             | do_mount_root ​                               |
 +|90_restore_config ​         | restore_config ​                               |
 +|99_10_run_init ​           | run_init ​                                     |
 +
 +Functions, in order, executed by this hook (doesn'​t list the functions only
 +called by other functions)
 +
 +^Function ​         ^ Description ​                                              ^
 +|init_hotplug ​    | Initialize hotplug, if needed (that is for devfs). ​ Hotplug or a device daemon is needed so that devices are available for use for preinit ​                                                                               |
 +|preinit_ip ​      | Initialize network interface (if one has been defined for as available for preinit) ​                                                      |
 +|pi_indicate_preinit| Send messages to console, network, and/or led, depending on which, if any, of these is present which say that we are in preinit mode   |
 +|failsafe_wait ​  | Emits messages (to network and console) that indicate the user has the option to enter failsafe mode and wait for the configured period of time (default two seconds) for the user to select failsafe mode                 |
 +|run_failsafe_hook | If user chooses to enter failsafe mode, run the *failsafe* hook (which at present doesn'​t return, which means no more functions from preinit_main get run on this boot)                                                |
 +|indicate_regular_preinit_boot| Emits messages to network, console, and/or LED depending on which (if any) is present, indicating that it's a regular boot not a failsafe boot                                                              |
 +|initramfs_test ​   | If initramfs is present run the *initramfs* hook and exit|
 +|do_mount_root ​   | Executes hook *preinit_mount_root* |
 +|restore_config ​   | If a previous configuration was stored by sysupgrade, restore it to the rootfs ​                                                          |
 +|run_init ​         | Exec the command defined by `pi_init_cmd` with the environment variables defined by `pi_init_env`,​ plus PATH `pi_init_path` ​       |
 +
 +Functions which are called by other functions, rather than directly as part of a hook.
 +
 +^Function ​           ^ Description ​                                            ^
 +|preinit_ip_deconfig | deconfigure interface used for preinit network messages etc |
 +|preinit_net_echo ​   | emit a message on the preinit network interface ​        |
 +|preinit_echo ​       | emit a message on the (serial) console ​                 |
 +|pi_indicate_led ​    | set LED status to indicate preinit mode                 |
 +|fs_wait_for_key ​    | wait for reset button press, CTRL-C, or <​some_key><​ENTER>,​ with timeout|
 +
 +==== failsafe ====
 +
 +Do what needs to done to prepare failsafe mode and enter it.
 +
 +^File                  ^ Description ​                                          ^
 +|10_indicate_failsafe| indicate_failsafe_led,​ indicate_failsafe ​          |
 +|99_10_failsafe_login| failsafe_netlogin,​ failsafe_shell ​                 |
 +
 +Functions, in order, executed by this hook (doesn'​t list the functions only
 +called by other functions)
 +
 +^Function ​            ^ Description ​                                           ^
 +|indicate_failsafe ​  | Emit message/​status to network, console, and/or LED (depending on which, if any, are present) indicating that the device is now in failsafe mode                                                                       |
 +|failsafe_netlogin ​  | Launch telnet daemon to allow telnet login on the defined network interface (if any)                                                   |
 +|failsafe_shell ​     | Launch a shell for access via serial console (if present) ​                                                                             |
 +
 +
 +Functions which are called by other functions, rather than directly as part of a hook
 +
 +^Function ​           ^ Description ​                                            ^
 +|indicate_failsafe_led| set LED status to indicate preinit mode                |
 +
 +==== preinit_mount_root ====
 +
 +Mount the root filesystem
 +
 +^File                  ^ Description ​                                          ^
 +|05_mount_skip ​        | check_skip ​                                           |
 +|10_check_for_mtd ​     | mount_no_mtd,​ check_for_mtd ​                          |
 +
 +
 +Functions, in order, executed by this hook (doesn'​t list the functions only
 +called by other functions)
 +
 +^Function ​            ^ Description ​                                           ^
 +|check_for_mtd ​       | Check for a mtd partition named rootfs_data. ​ If not present mount kernel fs as root (e.g. all_jjfs2 or squashfs only) and skip rest. |
 +|check_for_jffs2 ​     | Check if jffs2 formatted yet.  If not, mount ramoverlay and skip rest |
 +|do_mount_jffs2 ​      | find jffs2 partition and mount it, indicating result |
 +|rootfs_pivot ​        | if jffs2 mounted, make it root (/) and old root (squashfs) /rom , skipping rest on success|
 +|do_mount_no_jffs2 ​   | If nothing was mounted so far, mount ramdisk (ram overlay), skipping rest on success|
 +|do_mount_no_mtd ​     | If there was nothing mounted , mount /dev/root as root (/) |
 +
 +Functions which are called by other functions, rather than directly as part of a hook
 +
 +^Function ​           ^ Description ​                                            ^
 +|mount_no_mtd ​       | if there is not mtd partition named rootfs_data,​ mount /dev/root as / (root). ​ E.g. this can occur if the firmware filesystem is entirely a jffs2 partition, with no squashfs) |
 +|mount_no_jffs2 ​     | mount ramdisk (ram overlay) if there is rootfs_data,​ but it has not been formatted yet) |
 +|find_mount_jffs2 ​   | find and mount rootfs_data jffs2 partition on /jffs     |
 +|jffs2_not_mounted ​  | returns true (0) if jffs2 is not mounted ​               |
 +
 +==== initramfs ====
 +
 +No files or functions at this time.
 +
 +====== Firstboot Operation ======
 +
 +===== Main Firstboot Script =====
 +
 +  - Source common functions
 +  - Source functions for hooks
 +  - if block:
 +    if invoked as executable
 +         if called with `switch2jffs` parameter (i.e. from rcS)
 +             run hook `switch2jffs`
 +         if called standalone (e.g. from commandline)
 +             if there is a jffs2 partition mounted
 +                  run hook `jffs2reset`
 +             else
 +                  erase rootfs_data mtd partition
 +                  format
 +                  and remount it
 +             end
 +         end
 +   if sourced (that is not executed)
 +        set some variables
 +   end
 +
 +===== Hooks =====
 +
 +==== switch2jffs ====
 +
 +Make the filesystem that we want to be the rootfs, to be the rootfs
 +
 +^File                  ^ Description ​                                          ^
 +|10_determine_parts ​ |deterimine_mtd_part,​ determine_rom_part,​ determine_jffs2_part,​ set_mtd_part,​ set_rom_part,​ set_jffs2_part |
 +|20_has_mini_fo ​    ​|check_for_mini_fo ​                                  |
 +|30_is_rootfs_mounted|skip_if_rootfs_mounted ​                            |
 +|40_copy_ramoverlay ​ |copy_ramoverlay ​                                      |
 +|50_pivot ​             |with_fo_pivot ​                                       |
 +|99_10_with_fo_cleanup | with_fo_cleanup ​                                |
 +
 +Functions, in order, executed by this hook (doesn'​t list the functions only
 +called by other functions)
 +
 +^Function ​            ^ Description ​                                           ^
 +|determine_mtd_part | exit if no mtd partition at all                         |
 +|determine_rom_part | exit if not squashfs partition (firstboot not for all_jffs2) |
 +|determine_jffs2_part| figure out the jffs2 partition (assuming we have an mtd part|
 +|check_for_mini_fo | determine if we have mini_fo overlay in kernel. ​ If not run *no_fo* hook|
 +|skip_if_rootfs_mounted| attempt mount jffs2 on /​rom/​jffs2. ​ If partition already mounted exit |
 +|copy_ramoverlay ​    |copy the data from the temporary rootfs (on the ramdisk overlay over the squashfs) to the new jffs2 partition |
 +|with_fo_pivot ​     |make current jffs2 partition the root partition and the current root /rom |
 +|with_fo_cleanup ​   |clean up unneeded mount of ramdisk, if possible ​         |
 +
 +
 +Functions which are called by other functions, rather than directly as part of a hook
 +
 +^Function ​             ^ Description ​                                            ^
 +|set_mtd_part ​       | set variables for mtd partition ​                        |
 +|set_rom_part ​       | set variable for squashfs (rom) partition ​              |
 +|set_jffs_part ​      | set variable for jffs2 partition ​                       |
 +
 +==== no_fo ====
 +
 +Make the filesystem that we want to be the rootfs, to be the rootfs, given that we have no mini\_fo overlay filesystem
 +
 +^File                  ^ Description ​                                          ^
 +|10_no_fo_clear_overlay |no_fo_clear_overlay ​                           |
 +|20_no_fo_mount_jffs | no_fo_mount_jffs ​                                |
 +|30_no_fo_pivot ​    | no_fo_pivot ​                                        |
 +|40_no_fo_copy_ram_overlay | no_fo_copy_ram_overlay ​                  |
 +|99_10_no_fo_cleanup | no_fo_cleanup ​                                    |
 +
 +Functions, in order, executed by this hook (doesn'​t list the functions only
 +called by other functions)
 +
 +^Function ​            ^ Description ​                                           ^
 +|no_fo_clear_overlay | stop ramdisk overlaying the squashfs ​                |
 +|no_fo_mount_jffs ​ | attempt to mount jffs (work around problem with union). ​ If already mounted exit |
 +|no_fo_pivot ​       | make jffs root and old root /rom                       |
 +|no_fo_copy_ram_overlay| copy data from ram overlay to jffs2 overlay of squashfs |
 +|no_fo_cleanup ​     | get rid of extra binds and mounts ​                     |
 +
 +==== jffs2reset ====
 +
 +Reset jffs2 to defaults
 +
 +^File                  ^ Description ​                                          ^
 +|10_rest_has_mini_fo | reset_check_for_mini_fo ​                        |
 +|20_reset_clear_jffs | reset_clear_jffs ​                                  |
 +|30_reset_copy_rom | reset_copy_rom ​                                      |
 +
 +Functions, in order, executed by this hook (doesn'​t list the functions only
 +called by other functions)
 +
 +^Function ​            ^ Description ​                                           ^
 +|reset_check_for_mini_fo | Determine if the kernel supports mini_fo overlay|
 +|reset_clear_jffs ​  | if mini_fo is supported, erase all data in overlay and remount (resets back to '​pure'​ squashfs versions |
 +|reset_copy_rom ​    | if mini_fo is not supported, make symlinks and copy critical files from squashfs to jffs |
 +
 +====== Customizing the system ======
 +
 +**NB**: These files must be added to the *squashfs* (or if using a all_jffs2 system, to the jffs2). ​ That means, for instance adding it to the image'​s rootfs. ​ This can be done, for instace, by creating `${ROOTDIR}/​files/​filename` (with appropriate substitutions of course).
 +
 +===== Overriding Example =====
 +
 +{{page>​meta:​infobox:​dangerous&​noheader&​nofooter&​noeditbtn}}
 +
 +Customizing the system is quite simple. ​ We give an example of changing the message for preinit from '- preinit -' to '- setting the table for dinner -'
 +
 +Create a file that replaces the function `indicate_regular_preinit_boot`.
 +`pi_indicate_preinit` is defined in `20_indicate_preinit`,​ so we define our replace functions in `25_dinner_not_router`.
 +
 +`/​lib/​preinit/​25_dinner_not_router`
 +
 +     ​pi_indicate_preinit() { 
 +           echo "- setting the table for dinner -"
 +           ​preinit_net_echo "​Dinner is just about ready!"​
 +           ​pi_indicate_led
 +     }
 +     
 +This results in the following boot log:
 +
 + NET: Registered protocol family 17
 + 802.1Q VLAN Support v1.8 Ben Greear <​greearb@candelatech.com>​
 + All bugs added by David S. Miller <​davem@redhat.com>​
 + VFS: Mounted root (squashfs filesystem) readonly on device 31:2.
 + Freeing unused kernel memory: 132k freed
 + Please be patient, while OpenWrt loads ...
 + eth1: link forced UP - 100/full - flow control off/off
 + - setting the table for dinner -
 + Press CTRL-C or Press f<​ENTER>​ to enter failsafe mode
 + switching to jffs2
 + mini_fo: using base directory: /
 + mini_fo: using storage directory: /jffs
 + - init -
 +
 +The default boot log is
 +
 + NET: Registered protocol family 17
 + 802.1Q VLAN Support v1.8 Ben Greear <​greearb@candelatech.com>​
 + All bugs added by David S. Miller <​davem@redhat.com>​
 + VFS: Mounted root (squashfs filesystem) readonly on device 31:2.
 + Freeing unused kernel memory: 132k freed
 + Please be patient, while OpenWrt loads ...
 + eth1: link forced UP - 100/full - flow control off/off
 + - preinit -
 + Press CTRL-C or Press f<​ENTER>​ to enter failsafe mode
 + switching to jffs2
 + mini_fo: using base directory: /
 + mini_fo: using storage directory: /jffs
 + - init -
 +     
 +
 +===== Adding Example =====
 +
 +As another example we will add a message to failsafe, between the notice that we're in failsafe mode in the shell. ​ You could use this, for example, to create a text menu system, or to launch a simple web server (with cgi scripts) to permit the user to do failsafe things.
 +
 +We want to add the message, '​Remember,​ at this point there are no writable filesystems'​
 +
 +We create the file `50_failsafe_remember_no_rw`,​ in `/​lib/​preinit`
 +
 +    remember_no_rw() {
 +        echo "​Remember,​ at this point there are no writable filesystems"​
 +    }
 +    ​
 +    boot_hook_add failsafe remember_no_rw
 +    ​
 +This creates the function `remember_no_rw` and adds it to the failsafe hook, in between `10_indicate_failsafe` and `99_10_failsafe_login` which define the other functions in the `failsafe` hook.  This wasn't necessary for the previous example because the function was already in a hook.
 +
 +The boot log for this, when entering failsafe, is:
 +
 + VFS: Mounted root (squashfs filesystem) readonly on device 31:2.
 + Freeing unused kernel memory: 132k freed
 + Please be patient, while OpenWrt loads ...
 + eth1: link forced UP - 100/full - flow control off/off
 + - preinit -
 + Press CTRL-C or Press f<​ENTER>​ to enter failsafe mode
 + f
 + - failsafe -
 + Remember, at this point there are no writable filesystems
 +
 +
 + BusyBox v1.15.3 (2010-01-20 19:26:26 EST) built-in shell (ash)
 + Enter '​help'​ for a list of built-in commands.
 +
 +
 + ash: can't access tty; job control turned off
 +
 +   _______ ​                    ​________ ​       __
 + |       ​|.-----.-----.-----.| ​ |  |  |.----.| ​ |_
 + |   ​- ​  ​|| ​ _  |  -__|     ​|| ​ |  |  ||   ​_|| ​  _|
 + |_______|| ​  ​__|_____|__|__||________||__| ​ |____|
 +                  |__| W I R E L E S S   F R E E D O M
 +
 + KAMIKAZE (bleeding edge, r19235) ------------------
 +   * 10 oz Vodka       Shake well with ice and strain
 +   * 10 oz Triple sec  mixture into 10 shot glasses.
 +   * 10 oz lime juice  Salute!
 + ---------------------------------------------------
 +
 +
 +====== Architecture-specific notes ======
 +
 +Some architectures have additional files and functions (or overrides of the above functions) in order to accommodate specific needs of that hardware. ​ In that case the files are located in the source tree under ''​$ROOTDIR/​target/​linux/<​architecture[/​subarch]/​base-files/​lib/​preinit''​. ​ During build they are merged and appear under ''/​lib/​preinit''​ along with the rest.