ジャンル不定の日記です。

Buildrootのブート処理

Orange pi R1用OSをSPIフラッシュにのるサイズで作りたいと思って rootfsをoverlayfs にしたいと思ってるが、
Buildrootのブート処理を確認。

initrdとかinitramfsがない場合は /sbin/init が実行される。
BusyBox init の場合は、/sbin/init が /etc/inittab を処理する。

Buildrootの/etc/inittab
# /etc/inittab
#
# Copyright (C) 2001 Erik Andersen <andersen@codepoet.org>
#
# Note: BusyBox init doesn't support runlevels.  The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id        == tty to run on, or empty for /dev/console
# runlevels == ignored
# action    == one of sysinit, respawn, askfirst, wait, and once
# process   == program to run

# Startup the system
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts /dev/shm
::sysinit:/bin/mount -a
::sysinit:/sbin/swapon -a
null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd
null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin
null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout
null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr
::sysinit:/bin/hostname -F /etc/hostname
# now run any rc scripts
::sysinit:/etc/init.d/rcS

# Put a getty on the serial port
console::respawn:/sbin/getty -L  console 0 vt100 # GENERIC_SERIAL

# Stuff to do for the 3-finger salute
#::ctrlaltdel:/sbin/reboot

# Stuff to do before rebooting
::shutdown:/etc/init.d/rcK
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
上の方に説明書きしてあって親切。
書式はBusyBox以外ののinitと同じようだが、
:で区切って<id>:<runlevels>:<action>:<process>らしい。
runlevelがないので2番目は常に空。
idは他のinitだと固有のものをつけて、定義済みの特殊なやつもある感じなんだが、BusyBoxの場合は出力先を指定するだけな感じ?
actionは実行タイミングでprocessを実行するって感じかな?
actionにはone of sysinit, respawn, askfirst, wait, and onceが指定できると書いてあるが、詳細が書いてないし実際のコードには別のものも書かれててよくわからん。
sysinitとonceが別にあるってことはonceは絶対に1回しか実行されないの?
sysinitとwaitが別にあるってことはsysinitは非同期で実行される?

というわけなんだが、ググってたらBusyBox initのソースコードみたいの出てきて中にコメントで詳しく書かれてた。
/* Start these actions first and wait for completion */
#define SYSINIT     0x01
/* Start these after SYSINIT and wait for completion */
#define WAIT        0x02
/* Start these after WAIT and *dont* wait for completion */
#define ONCE        0x04
/*
 * NB: while SYSINIT/WAIT/ONCE are being processed,
 * SIGHUP ("reread /etc/inittab") will be processed only after
 * each group of actions. If new inittab adds, say, a SYSINIT action,
 * it will not be run, since init is already "past SYSINIT stage".
 */
/* Start these after ONCE are started, restart on exit */
#define RESPAWN     0x08
/* Like RESPAWN, but wait for <Enter> to be pressed on tty */
#define ASKFIRST    0x10
/*
 * Start these on SIGINT, and wait for completion.
 * Then go back to respawning RESPAWN and ASKFIRST actions.
 * NB: kernel sends SIGINT to us if Ctrl-Alt-Del was pressed.
 */
#define CTRLALTDEL  0x20
/*
 * Start these before killing all processes in preparation for
 * running RESTART actions or doing low-level halt/reboot/poweroff
 * (initiated by SIGUSR1/SIGTERM/SIGUSR2).
 * Wait for completion before proceeding.
 */
#define SHUTDOWN    0x40
/*
 * exec() on SIGQUIT. SHUTDOWN actions are started and waited for,
 * then all processes are killed, then init exec's 1st RESTART action,
 * replacing itself by it. If no RESTART action specified,
 * SIGQUIT has no effect.
 */
#define RESTART     0x80

sysinitも並列に実行されるわけではなくプロセスの終了を待つぽい。
waitはsysinitよりもあとに実行される。なのでwaitは要らないような・・・
onceはwaitよりもあとに実行。これは非同期で実行されるぽい。
respawnは実行して終了したら再実行。askfirstも再実行だがEnterの入力を待つ。
他のactionはイベント発生時に実行されるやつだね。

これでswich_rootとかpivot_rootするスクリプトかなんかを目的を達成できそうな気もするが、最初にやりたいからactionはsysinitで良さそう。

rootfsの変更処理はまだ試してないが、
起動時は/etc/inittabから/etc/init.d/rcSが実行されることがわかった。
/etc/init.d/rcSは/etc/init.d以下にある S??* という名前のプログラムに引数 start をつけて実行する。
??の部分は2桁の数字でファイル名順に実行されるので数字が小さいほうが先に実行される。

モジュールを自動ロードするのに /etc/modprobe.d とか無いんで、
/etc/init.d/S30modprobe を作って8189esを自動ロードするように作ってみた。
startとか要らないんで、
#!/bin/sh
modprobe 8189es
だけ。
/etc/init.d/S40network が起動時に自動でifupするスクリプトなんで、その前のほうがいいと思ったんでS30にした。

目的のrootfsの変更はまだやってないが、眠すぎなんで今日はここまでで寝る。