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

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くらいは捻出できるかな?

OSの起動はできたんで、あとはdnsmasq、hostapd、pppd、uhttpd、nftablesの設定かな。