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

OPI R1のAP化ができない・・・

Orange pi R1をSPIフラッシュブートでwifiアクセスポイントにする計画も、MTDでOSの起動ができてもう少しだと思ったが、またハマってる・・・
hostapdでAPは出てくるんだが接続できない状態。

まず hostapd dnsmasq nftablesを全部設定したが、nftablesはパッケージ入れるだけじゃなくてkernelでnftablesを有効にする必要があった。
nftコマンドを使うとNETLINKがないとか言われたので、
[*] Networking support  --->
  Networking options  --->
    <*> NETLINK: socket monitoring interface
NETLINKを有効にした。
それとnftablesはNetfilterってのの機能みたいで、
[*] Networking support  --->
  Networking options  --->
     <*> Netfilter connection tracking support
     <*> Netfilter nf_tables support
       <*>   Netfilter nf_tables masquerade support
       <*>   Netfilter nf_tables nat module
     IP: Netfilter Configuration  --->
       [*] IPv4 nf_tables support
こんな感じで有効にしないとnftコマンドでnatを設定する際にエラーが出るのだが、
Netfilter nf_tables nat moduleが隠れててどこにあるのかわからなかった。
Netfilter nf_tables support を有効にすると IPv4 nf_tables support が出てくる。
さらに Netfilter connection tracking support を有効にすると Netfilter nf_tables nat module が出てくる。
Netfilter nf_tables nat module を有効にすると Netfilter nf_tables masquerade support が出てくる。
て感じで順番に設定しないと項目がない。

まあ、そんなわけなんだがスマホとノートPCで試したが、アクセスポイントは出てくるんだが接続できない。
クライアント側にもサーバー側にもエラー内容が表示されないから困る・・・

dnsmasq と nftables 以前にhostapdで失敗してるぽいんで、DHCPが使えなくなるがdnsmasqとnftablesを切った状態で試してるがわからん。
hostapdの起動時はrfkillがないとか/dev/randomがどうとかメッセージ出るんでそのへん試してるところ。

SPIフラッシュから起動できた

やっとのことで、Orange pi R1をSPIフラッシュから起動できた。
昨日のパーティションパーティション割りで4kB単位で問題ないと思ってたが、erasesizeが64kBになるのでそれを下回るとリードオンリーになっちゃうようなので64kB単位にした。
u-boot、boot.scr、zImage、dtbは一緒のパーティションに入れちゃってもいいかもしれない。

boot.cmd
setenv mtdparts spi0.0:512k(U-Boot),64k(boot.scr),5M(zImage),64k(dtb),7M(ro),-(rw)
if load mmc 0:1 ${fdt_addr_r} /${fdtfile};then
    load mmc 0:1 ${kernel_addr_r} /zImage
    setenv bootargs mtdparts=${mtdparts} root=/dev/mmcblk0p2 init=/init.sh console=ttyS0,115200
    bootz ${kernel_addr_r} - ${fdt_addr_r}
fi
setenv bootargs mtdparts=${mtdparts} root=/dev/mtdblock4 init=/init.sh console=ttyS0,115200
mtd read nor0 ${kernel_addr_r} 0x90000 0x500000
mtd read nor0 ${fdt_addr_r} 0x590000 0x10000
bootz ${kernel_addr_r} - ${fdt_addr_r}
boot.scrはSDブート用とSPIブート用で共通にした。
SDからブートできそうならSDブートになる。
カーネルパラメータのmtdpartsでパーティション情報を渡すと割られる。
spi0.0はlinux上で見えるSPIフラッシュのデバイス名。
オフセットはなしでサイズだけ書いて最後のパーティションのサイズを-にすれば使い切れる。
イメージサイズに合わせて最適化しようかとも思ったがとりあえず固定にした。

mtdpartsをカーネルが受け取るのに、CONFIG_MTD_CMDLINE_PARTS=y でビルドしなおした。受け取れなくて結構ハマった。
上記設定すれば/dev/mtdXは割られるのだが、mountするのに/dev/mtdblockXが必要。
CONFIG_MTD_BLOCK=y を有効にしてビルドすると/dev/mtdblockXが出てきてマウントできるようになる。これまたハマった・・・

昨日やった部分だが
include/configs/sunxi-common.h
#define CONFIG_EXTRA_ENV_SETTINGS \
/*
    CONSOLE_ENV_SETTINGS \
    MEM_LAYOUT_ENV_SETTINGS \
    DFU_ALT_INFO_RAM \
    "fdtfile=" FDTFILE "\0" \
    "console=ttyS0,115200\0" \
    SUNXI_MTDIDS_DEFAULT \
    SUNXI_MTDPARTS_DEFAULT \
    "uuid_gpt_esp=" UUID_GPT_ESP "\0" \
    "uuid_gpt_system=" UUID_GPT_SYSTEM "\0" \
    "partitions=" PARTS_DEFAULT "\0" \
    BOOTCMD_SUNXI_COMPAT \
    BOOTENV
*/\
    MEM_LAYOUT_ENV_SETTINGS \
    "fdtfile=" FDTFILE "\0" \
"load_scr=if load mmc 0:1 $scriptaddr /boot.scr;then echo Found boot.scr in mmc;else mtd read nor0 $scriptaddr 0x80000 0x10000;fi;\0"\
"distro_bootcmd=sf probe;run load_scr;source $scriptaddr;\0"

#else /* ifndef CONFIG_SPL_BUILD */
こんな感じで、自動実行されるdistro_bootcmdでSDかSPIのboot.scrを実行する。

イメージをMTDに書き込む際は全体のイメージをddで作ってSDブートのOSで書き込もうとしたのだが、
flashcpはパーティション単位でしか書き込めない。というか、カーネル起動オプションでMTDを割ると全体のデバイスは出てこなくて割られたデバイスしかなくなるのね。
というわけで、個別に母艦からwgetしてflashcpした。
どっかで、flashcpはデバイスサイズとイメージサイズが一致しないと書き込めないとか見た気がするんだが、そんなことはなかった。サイズはいじらないで書き込めた。

/init.sh
#!/bin/sh
/bin/mount -t proc proc /proc
if [ -e /dev/mmcblk0p3 ];then
  /bin/mount /dev/mmcblk0p3 /mnt/rw
else
  /bin/mount /dev/mtdblock5 /mnt/rw
fi
/bin/mount -o bind /mnt/rw/etc /etc
/bin/mount -o bind /mnt/rw/home /home
exec /sbin/init
/initの前に実行するスクリプトもmmcとspi共通にした。
/がroなSquashfsにして/etcをrwにするために、/etc/inittabを処理する/initは使えないので、先に/etcをマウントする。

また丸1日ハマったが、SD抜いて起動できるようになった。

rwパーティションのイメージは2MBで作ってあるので、
# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 6144      6144         0 100% /
devtmpfs                116608         0    116608   0% /dev
/dev/mtdblock5            2011       860      1049  45% /mnt/rw
/dev/mtdblock5            2011       860      1049  45% /etc
/dev/mtdblock5            2011       860      1049  45% /home
tmpfs                   125312         0    125312   0% /dev/shm
tmpfs                   125312        28    125284   0% /tmp
tmpfs                   125312        24    125288   0% /run
こんな感じ。
起動後に拡張するつもりだったが、resize2fsとかpartedとかないし、mkfsもなく、
resize2fsがBuildrootでビルドできなくて、別途ビルドしたのとか別ディストリのresize2fsを持ってきたりしたがエラーになっちゃったんで更にハマった。
mkfsは有効にしてなかったが、mke2fsが初期状態で有効だったんで、一旦コピーしてmke2fsして中身戻した。
# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 6144      6144         0 100% /
devtmpfs                116608         0    116608   0% /dev
/dev/mtdblock5            3343       852      2319  27% /mnt/rw
/dev/mtdblock5            3343       852      2319  27% /etc
/dev/mtdblock5            3343       852      2319  27% /home
tmpfs                   125312         0    125312   0% /dev/shm
tmpfs                   125312        28    125284   0% /tmp
tmpfs                   125312        24    125288   0% /run
こんな感じに。
余裕はないけど2.5MBくらい使える。
頑張ればあと2MBくらいは捻出できるかな?

U-Bootのデフォルト環境変数を設定した

Orange pi R1をMTDブートさせたい件で、U-Bootのデフォルト環境変数を設定した。

include/configs/sunxi-common.h の CONFIG_EXTRA_ENV_SETTINGS で設定できる。
#define CONFIG_EXTRA_ENV_SETTINGS \
/*
    CONSOLE_ENV_SETTINGS \
    MEM_LAYOUT_ENV_SETTINGS \
    DFU_ALT_INFO_RAM \
    "fdtfile=" FDTFILE "\0" \
    "console=ttyS0,115200\0" \
    SUNXI_MTDIDS_DEFAULT \
    SUNXI_MTDPARTS_DEFAULT \
    "uuid_gpt_esp=" UUID_GPT_ESP "\0" \
    "uuid_gpt_system=" UUID_GPT_SYSTEM "\0" \
    "partitions=" PARTS_DEFAULT "\0" \
    BOOTCMD_SUNXI_COMPAT \
    BOOTENV
*/\
    MEM_LAYOUT_ENV_SETTINGS \
    "fdtfile=" FDTFILE "\0" \
"load_scr=if load mmc 0:1 $scriptaddr /boot.scr;then echo Found boot.scr in mmc;else mtd read nor0 $scriptaddr 0x80000 0x1000;fi;\0"\
"distro_bootcmd=sf probe;run load_scr;source $scriptaddr;\0"

#else /* ifndef CONFIG_SPL_BUILD */
初期設定はまるごとコメントアウトした。
末尾に空行が入らないといけないのと、途中に改行が入るといけないみたいなのでエスケープに注意。
MEM_LAYOUT_ENV_SETTINGS は無いとscriptaddrとかkernel_addr_rとか使えなくなる。
fdtfileもboot.scrで使うので入れた。

初期設定でビルドするとdistro_bootcmdが自動実行されるのでこれを変えた。
SPIフラッシュを有効にして、load_scrを実行して、スクリプトを処理する。
load_scrは長いんで分けたが、SDの第1パーティションに/boot.scrがあればそれをロード。なければSPIフラッシュからオフセット512kBの4kBをロード。
オフセットの512kBまでにU-Boot本体を入れる。boot.scrは4kB。
搭載フラッシュは256B単位で読めるようなんだが、MTDは4kB単位で使うのが基本ぽい?
てな感じで、SPIフラッシュとSDカードの両方で使える感じにした。
boot.scrも共通で使えるようにしたい。init.shも共通にできるかな。

U-bootでSPIフラッシュ認識した!

Orange pi R1でU-bootでSPIフラッシュを認識しなかった件ですごい苦戦したがやっとできた。

u-bootでspiフラッシュを使おうとすると
=> sf probe
Invalid bus 0 (err=-19)
Failed to initialize SPI flash at 0:0 (error -19).
こんな感じになって数日解決できなかった。

原因は、
arch/arm/dts/sun8i-h2-plus-orangepi-r1.dts
でデバイスの設定がされてるのだが、
&spi0 {
    status = "okay";

    flash@0 {
        compatible = "mxicy,mx25l12805d", "jedec,spi-nor";
    };
};
↑この部分まるごとコメントアウトされてた。
ブロックまるごとコメントアウトとは思わんし、.dtsファイルだからKateのハイライトが効いてなくてコメントに気づかなかった。
これアンコメントしたらdm treeでデバイスが出てきた。

それだけだとsf probeでエラーが出るのは変わらないのだが、
    aliases {
        ethernet1 = &rtl8189etv;
        spi0 = &spi0;
    };
spi0のエイリアスを設定すると利用できるようになる。

=> mtd list
List of MTD devices:
No MTD device found
=> sf probe
SF: Detected mx25l12805d with page size 256 Bytes, erase size 64 KiB, total 16 MiB
=> mtd list
List of MTD devices:
* nor0
  - type: NOR flash
  - block size: 0x10000 bytes
  - min I/O: 0x1 bytes
  - 0x000000000000-0x000001000000 : "nor0"
出てきた。

Orange pi R1 のSPIフラッシュはMacronixみたい

Orange pi R1のOSをSPIフラッシュに入れようとしているが、まずSDのu-bootでmtdコマンドを使ってみることにした。
u-bootのmenuconfigで、
Command line interface  --->
Device access commands  --->
[*] mtd
Filesystem commands  --->
[*] MTD partition support

Device Drivers  --->
[*] SPI Support  --->
MTD Support  --->
[*] Legacy SPI Flash Interface support
[*] Winbond SPI flash support
をチェックして再ビルド。
でmtd認識しない・・・

Armbian使ったときはmtd認識してたんでLinuxの方は使えると思ってたが、確認してみたら無かった。
というわけで、linuxも再ビルド。
menuconfigでWinbondのドライバが見当たらなくて時間かかったが、
<*> Memory Technology Device (MTD) support  --->
<*>   SPI-NOR device support  --->
この2つだけ有効にしたら認識した。
固有のドライバは要らないみたい。

そして、作業中にルーペ+スマホカメラでボードのチップを確認してみたらMXICとか書いてある。
Orange pi R1 のSPIフラッシュはmiZyのとこでWinbondとかって記述があったのでてっきりWinbondと思ってたんだが、
WinbondじゃなくてMacronixみたい・・・

あと、linuxビルドの際に前回ビルドしたときにサウンドとか外して3.7MBに減らしてたが今回4.1MBに増えた。

modules.builtin 確認したらサウンドとか入っちゃってるし・・・
defconfigし直しちゃってたみたいね・・・
逆に要るやつ無くなっちゃってるし再ビルドしなきゃ・・・

プリンタドライバを入れた

先日メインPCがぶっ壊れて再インストールしてからプリンタ(DCP-J552N)のドライバを入れてなかったが入れた。
以前は公式のrpmを落として展開して手動でコピーしてたが、
今回はAURにあるDCP-J552DWのパッケージを落としてきて改造してDCP-J552Nにした。
ちなみに名前が違うだけでDCP-J552DWのドライバでもDCP-J552Nは利用できる。

PKGBUILD、brother-dcpj552n.install、 fix_lp.patch の3ファイルの中身を
dcpj552dw  → dcpj552n
DCP-J552DW  → DCP-J552N
に名前を変更。
URLを
https://download.brother.com/welcome/dlf100549/dcpj552nlpr-3.0.0-1.i386.rpm
https://download.brother.com/welcome/dlf100551/dcpj552ncupswrapper-3.0.0-1.i386.rpm
に変更。

で makepkg するとmd5sumで失敗するがダウンロードはされてるのでmd5sum を確認して PKGBUILD 記載のmd5sumsを変更する。

で、プリンタがインストールされるがUSB接続用なのか利用できない。
一旦プリンタを消して、
ipp://IPアドレス:631/ipp
でネットワークプリンタを追加すれば利用可能。

以前の記事でスキャナはbscan4て書いてあるが、brscan4だね。
検索しても出てこないからなくなったのかと思った。
こちらは以前と同じくAURで入れた。

/をsquashfsで/etcと/homeだけext2にした

Orange pi R1のSPIフラッシュにOSのせるためにrootfsを圧縮ファイルシステムのsquashfsにした上で書き込みできるようにoverlayfsを使うつもりだったが、
難しくて断念して/etcと/homeだけ書き換えできるようにした。

まずrootfsをoverlayfsにするつもりだったが、
overlayfsは2つ以上のディレクトリを重ねるシステムなので、片方にリードオンリーなsquashfsを使って書き換えできるようにするには2つのファイルシステムを先にマウントする必要がある。
なのでkernel起動パラメータroot=の部分で指定することはできない。

squashfsで起動したあとでoverlayfsをマウントして/を変更する手段として、chroot pivot_root switch_rootを考えたが、
  chroot : 現在のプロセスのみ/を変更する。
  pivot_root : 元の/には別のファイルシステムがマウントされていてはいけない。元の/と新/は別のファイルシステムでなければいけない。
  switch_root : 元の/にあるファイルは全削除される。
らしい。
システム全体を変更したいのでchrootはナシ。
switch_rootは、元の/のファイルが削除されるというのはなんでだろ?マウントポイントがなくなるだけではないの?initramfsで使われることが多いみたいだが一時的なramディスクでないと問題あり?
pivot_rootはなんか制約が多い。新/が別のファイルシステムだと/の下にマウントしなきゃいけないから2つのファイルシステムは必ず存在することになるのでわかりにくい。

まあとりあえず実際にpivot_rootとかswitch_rootを試してみようかと思ったが、起動中のシステムでやろうとしてもエラーでうまく行かなかった。
initrdとinitramfsも試そうとしたが、どうもkernelパラメータからroot=を外すとkernel panicしちゃうんでなにか間違えてる・・・
miZyとかopenWRTは/がoverlayfsだったりするので方法はあるはずだが・・・

というわけでうまく行かなかったのだが、
書き換えが必要なのは /etc と /home だけだよね。
そこをどうにかしようと考えて、rwなパーティションを/mnt/rwにマウントして、その下のディレクトリを/etcと/homeにマウントすることにした。

ディレクトリ作ったりしてる作業中に、rootfsの/etcをrw/etcに全コピーしてして/etcを消すときに気づいたが、
linux起動時は/sbin/initが実行されて、/etc/inittabが処理され、/etc/fstabに記載されたデバイスがマウントされる。
/etc/inittabが別デバイス上じゃ読めないじゃん!

ということで再度悩んだが、
kernel起動パラメータのinit=で/sbin/init以外を指定すればinitプログラムを代えることができる!
と気づいた。

/init.sh
#!/bin/sh
/bin/mount -t proc proc /proc
/bin/mount /dev/mmcblk0p3 /mnt/rw
/bin/mount -o bind /mnt/rw/etc /etc
/bin/mount -o bind /mnt/rw/home /home
exec /sbin/init
kernel起動パラメータで最初に実行するinit。
rwデバイスをマウントして、下にあるetcとhomeを/etcと/homeにbindする。
最初procをマウントしなかったらデバイスのmountができなかった。
マウントしたら本来の/sbin/initを実行。

/etc/inittab (の起動処理の部分)
# 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
rootfsの/etcは空にしてるんでrwデバイス側。先に/init.shでbindされるんで/etc/inittabとして扱える。
procのマウントは/init.sh側に移したのでコメントアウト。
メモリは256MBも積んでるがストレージ(SPIフラッシュ)は16MBしかないのでswap要らん。というわけでkernelビルド時に無効にしてるんでswaponもコメントアウトしといた。
/dev/ptsと/dev/shmは最初からあるからmkdirする必要あるのか?思って一旦コメントアウトしたが、/devにdevtmpfsがkernelにマウントされるから無くなるんだね。mkdirしないとエラー出た。
mkdirするには/をrwでremountする必要があるってことみたい。

/etc/fstab
# <file system> <mount pt>      <type>  <options>       <dump>  <pass>
/dev/root       /               ext2    rw,noauto       0       1
proc            /proc           proc    defaults        0       0
devpts          /dev/pts        devpts  defaults,gid=5,mode=620,ptmxmode=0666   0       0
tmpfs           /dev/shm        tmpfs   mode=0777       0       0
tmpfs           /tmp            tmpfs   mode=1777       0       0
tmpfs           /run            tmpfs   mode=0755,nosuid,nodev  0       0
sysfs           /sys            sysfs   defaults        0       0
/dev/mmcblk0p3  /mnt/rw         ext2    rw,noauto       0       0
これもrwデバイス側。
/mnt/rwは手動マウントするんで追加しなくても起動するが、シャットダウン時に自動アンマウントさせるためにnoautoで追加しといた。
これでumountしてくれる?

こんな感じで、/をsquashfsにした上で/etcの変更ができるシステムができた。
# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 6016      6016         0 100% /
devtmpfs                116652         0    116652   0% /dev
/dev/mmcblk0p3            9911       920      8479  10% /mnt/rw
/dev/mmcblk0p3            9911       920      8479  10% /etc
/dev/mmcblk0p3            9911       920      8479  10% /home
tmpfs                   125356         0    125356   0% /dev/shm
tmpfs                   125356        28    125328   0% /tmp
tmpfs                   125356        24    125332   0% /run
/は6MBになった。
他にboot用のパーティションがzImageとかで頑張っても4MBまでしか削れない。
余裕もたせてboot=6MB,root=8MBで残り2MBくらいか?
と思ったが、どうせ書き込み用のイメージ化しなきゃいけないんだし最適化するスクリプトでも作るか。
そうすると10MBくらいに収まるんで残りのrwは6MBくらい使えるか?

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で良さそう。

今日もBuildroot

昨日寝てる間にlighttpdをuhttpdに置き換えてBuildrootし直したのだが、容量が減るどころか微妙に増えた気が・・・
って感じだったのだが、lighttpdは消したのだが/usr/lib以下にlighttpd関連が残ってた。
なので make distclean してからbuildrootし直した。
13MB強になったので4MBほど減ったかな?
と思ったが、8189es入れたら15MB強になった。
まあ、httpdがない状態でも13MB強だったからuhttpdはほとんど消費しないかも。
httpdは入れときたいしこれで行く。
8189es.koは1.5MB近くあるのね・・・

だいぶ記事が別れてるんで、 Buildroot の手順まとめとく。

$ git clone git://git.buildroot.net/buildroot --depth=1
$ make orangepi_r1_defconfig
$ make menuconfig
$ make ARCH=arm CROSS_COMPILE=arm-none-eabi-
これで Orange pi R1 用のOSイメージができちゃう。
が、zImage とかは別途調整したいんで  rootfs.ext2 だけ使ってる。

BusyBoxの機能は package/busybox/busybox.config で設定できる。
標準で depmod がないが
# CONFIG_DEPMOD is not set

CONFIG_DEPMOD=y
に代えれば depmod できるようになる。
Buildrootでインストールできるkmodを入れれば代用できると思うがBusyBoxに機能追加のほうが小さいと思う。

menuconfigでは、
Toolchain  --->
    Custom kernel headers series (5.4.x)
    [*] Enable WCHAR support
System configuration  --->
    [*] Enable root login with password
        (0000) Root password
Kernel  --->
    [*] Linux Kernel
        Kernel version (Custom version)  --->
            (5.4.12) Kernel version
Target packages  --->
    Networking applications  --->
        [*] dnsmasq
            [ ]   tftp support
        [*] hostapd
        [*] nftables
        [*] openssh
        [*] pppd
        [*] uhttpd
    Shell and utilities  --->
        [*] sudo
    Text editors and viewers  --->
        [*] nano
こんな感じで、rootパスワードの設定と、KErnelを5.4.12に変更。
5.4.xにした場合はCustom kernel headers series (5.4.x)にしないと途中でエラー落ちする。
nanoをインストールするのにEnable WCHAR supportが必要。
パッケージは、
dnsmasq hostapd nftables openssh pppd uhttpd sudo nano
を入れた。
dnsmasqのtftpdは明らかに要らないんで消した。
hostapdにも要らない機能ありそうだがよくわからないのでそのままにした。

Squashfsマウントできた

Orange pi R1用OS作成でSquashfsマウントできた。initramfsなしで。
リードオンリーになっちゃうけど、これで/sbin/init実行できるから/etc/fstabにoverlay書けばいいんじゃないかな?

まずinitramfsを使ってみようと思って、実機の方で作業しようと思ったがBusyBoxのcpioが違っててやり方がわかんなかったので母艦でやった。
$ su
# mount /dev/sdg2 /mnt
# mkdir /tmp/initrd
# mkdir /tmp/initrd/dev
# mkdir /tmp/initrd/bin
# mkdir /tmp/initrd/mnt
# cp -a /mnt/bin/busybox /tmp/initrd/bin
# ln -s busybox /tmp/initrd/bin/sh
# ln -s busybox /tmp/initrd/bin/mount
# ln -s busybox /tmp/initrd/bin/switch_root
# nano /tmp/initrd/init
# chmod 744 /tmp/initrd/init
# mount /dev/sdg2 /mnt
# cd /tmp/initrd
# find . | cpio -o | gzip -9 -c > /mnt/initramfs.img
こんな感じの作業内容かな?
作業ディレクトリのしたに dev bin mnt を作成。
binにbusyboxをコピーしてシンボリックリンクで sh mount switch_root を作る。
作業ディレクトリの直下に init スクリプトを作る。
initの内容は
#!/bin/sh
/bin/mount -t devtmpfs devtmpfs /dev
/bin/mount /dev/mmcblk0p2 /mnt

exec /bin/switch_root /mnt /sbin/init
/dev にdevをマウントする。
/mnt にrootfsをマウントする。
/mnt にswitch_root で/sbin/init を実行。
て感じかな?
initを実行可能にして作業ディレクトリをinitramfs化する。

てな感じでやってブートしてみてエラーでなかったが、もともとextのrootfsでinitramfsなしでブートできてたからよくわからん。
というわけで、rootfsをSquashfsにして起動してみたがダメ。initramfsなしでブートしてもダメ。
kernelをSquashfs有効にしないで作ってるから当然w

kernel作り直しだが、menuconfigの Miscellaneous filesystems の下にSquashfsあった。
これ有効にしてリビルド。
extのrootfsで起動確認したあとでSquashfsで起動してみたが、initramfsなしで起動できた。
# df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 7424      7424         0 100% /
devtmpfs                116652         0    116652   0% /dev
tmpfs                   125356         0    125356   0% /dev/shm
tmpfs                   125356        32    125324   0% /tmp
tmpfs                   125356        24    125332   0% /run
圧縮しても7MBで、u-bootとzImage等で別途5MBくらい必要だから余裕ないね。
今回のリビルドの際に要らないもん消したからzImageは4MB割ってるがあまり削減余地はなさそう。