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

u-bootとlinuxのビルドやってみたが・・・

Orange pi R1をSPIフラッシュを使って運用したいので、とりあえずSDブートで自ビルドしてみた。

u-boot
$ git clone git://git.denx.de/u-boot.git
$ cd u-boot
$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- orangepi_r1_defconfig
$ make ARCH=arm CROSS_COMPILE=arm-none-eabi-
u-boot-sunxi-with-spl.bin ができあがる。
git コマンドに --depth=1 オプションをつけたほうが良かったかも。
バージョンが大量にある場合に --depth=1 だと1個しか持ってこないらしい。
makeの際に arm-none-eabi-gcc と swig が必要だった。クロスコンパイラは当然なきゃ無理だね。

kernel
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git --depth=1
$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- sunxi_defconfig
$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- menuconfig
$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- zImage
$ make ARCH=arm CROSS_COMPILE=arm-none-eabi- dtbs
arch/arm/boot/zImage と arch/arm/boot/dts/sun8i-h2-plus-orangepi-r1.dtb が出来上がった。
bcコマンドを追加インストールの必要があった。
menuconfigはとりあえず何もいじってない。

フォーマットとu-bootのインストール
SDをfdiskでシングルパーティションにしてext2でフォーマットした。
$ sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8
でu-bootをインストール。
bsが1024でseekが8なんでデバイスの先頭から8KiBの位置にインストールされる。
この位置がAllwinnerが実行するブートローダーのアドレスってことだろうが、フォーマットしたファイルシステムが壊れないの?
と思って考えたが、
デバイスの先頭から512byteでMBRが入ってる。
fdiskでパーティションを作成すると先頭は2048セクタになる。1セクタ512byteだから1MB。
というわけで、空き領域に入れてるんだね。

rootfsの展開
rootfsはArch Linux ARMのものを使おうとした。
ext2でフォーマットしたSDのパーティションをマウントして、
$ sudo bsdtar xf ArchLinuxARM-armv7-latest.tar.gz -C mnt
で展開した。
bsdtarではなく普通のtar使うと、「tar: 未知の拡張ヘッダキーワード 'LIBARCHIVE.xattr.security.capability' を無視」とか警告が出た。
/bootにはzImageとdtbsにいっぱいファイルが入ってるので消した。
initramfs-linux.img も消したけど、無いとだめだよね。というわけで戻した。
消したあとに作ったzImageとsun8i-h2-plus-orangepi-r1.dtbを/bootに入れた。

boot.cmd
setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p1 rootwait rootfstype=ext4
load mmc 0:1 ${kernel_addr_r} /boot/zImage
load mmc 0:1 ${fdt_addr_r} /boot/${fdtfile}
load mmc 0:1 ${ramdisk_addr_r} /boot/initramfs-linux.img
bootz ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r}
最初のパーティションがfatかextXで、/boot.scr か /boot/boot.scr があるとu-bootは読み込んでくれるらしい。
boot.scrはファイル名は別でもいいと思うがテキスト形式の boot.cmd から mkimage コマンドでboot.scrに変換できる。
$ sudo mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "Orange Pi R1 boot script" -d boot.cmd mnt/boot/boot.scr
これで mnt/boot/boot.scr が作成される。

で起動してみたら、
Starting kernel ...
で止まる・・・
boot.cmd いろいろいじってみたが解決せず。
正しいサイズでロードしてるのは確認できるので、u-bootは問題なく、kernelの起動オプションに問題があるかinitに問題があるかなのかな?

u-bootは /boot/extlinux/extlinux.confがあるとextlinuxでブートしてくれるらしいんで、
extlinux.conf
TIMEOUT 100
DEFAULT default
MENU TITLE Boot menu
LABEL default
    MENU LABEL Default
    LINUX /boot/zImage
    FDT /boot/sun8i-h2-plus-orangepi-r1.dtb
    APPEND root=/dev/mmcblk0p1 rootwait console=ttyS0,115200n8
    INITRD /boot/initramfs-linux.img

LABEL exit
    MENU LABEL Local boot script (boot.scr)
    LOCALBOOT 1
こんな感じで試してみたが、こっちも、
Starting kernel ...
で止まる。

Arch Linuxのrootfsを使ったのが良くなかったか?

ArmbianでOrange pi R1をルーター化1

メインPCが復活(再インストール)したんで、Orange pi R1のルーター化に挑戦した。
miZyは読み込み専用になっちゃうし、OpenWRTはwifiデバイスを使うのが難しそうだったし、どうせSDになるならArmbianでいいや。
というわけで、とりあえずArmbianを使ってルーター化に挑戦することにした。

Orange pi R1は有線インターフェイスが2つあるが、Armbianだとeth0とudevが命名したデバイスだったが、eth0とeth1にしたい。
公式の製品ページ見ると、eth1はボードのシリアルピンの側にあるmacアドレスの書いたシールが貼ってある方みたい。
こっちがRTL8152Bでeth0の方がCPU内臓の。
/etc/udev/rules.d/10-network.rulesを
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="macアドレス", NAME="eth1"
で設定したらeth1になる。
/etc/udev/rules.d/以下にあればファイル名はどうでもいい。

UTCになってたからタイムゾーンの設定をしようとしたのだが、armbian-configというArmbianの設定ツールがあるらしいので入れて使ってみた。
そしたら、
Network > Hotspot なる項目が!
これやったらアクセスポイント化に使えるhostapdを設定してくれた。
のだが、ほとんど手動で書き換える必要があったから微妙かな・・・
armbian-configは最初シリアルコンソールで使ったが、画面崩れてまともに操作できないのでsshで接続して使ったほうが良かった。

armbian-configで設定したらできた?
hostapdの設定ファイルは /etc/hostapd.conf にあった。
country_code=JP
に変更したのと、wpa_passphraseにパスフレーズを変更した。
最初USになってたが、JPじゃないと違法電波が飛ぶかもしれないらしい。

armbian-config でHotspot設定をしたら wlan0 にIPアドレスが設定されてたが、
設定ファイルは /etc/network/interfaces.d/armbian.ap.nat みたい。
172.からのクラスB?アドレスが設定されてたが、192.168からの見慣れたアドレスにしたいので変えた。
/etc/network/interfaces.d/armbian.ap.nat
# armbian NAT hostapd
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.1.1
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
プライベートアドレスの仕様忘れてたんで調べたが、
ネットワーク範囲の先頭と末尾のアドレスは割り当てられないので、192.168.1.0-192.168.1.255のネットワークの場合192.168.1.0と192.168.1.255はアドレスに使えないので192.168.1.1になる。
192.168.0.0-192.168.0.255のネットワークにすることも考えたが、ルーターを2台置くような感じにすると192.168.0.0-192.168.255.255の範囲で上位ネットワークを作ることになるので3桁目も0にしないほうが良さそう。

再起動したらwlan0のアドレスが予定通り192.168.1.1に変わってたが、起動ログで dnsmasq がエラー。
これは小規模なdnsサーバーとdhcpサーバーとして機能するサービスみたいで、ルーターにするのに丁度いいね。
設定ファイルは /etc/dnsmasq.conf にあった。
interface=wlan0
#listen-address=192.168.1.1
bind-interfaces
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=192.168.1.100,192.168.1.150,12h
listen-addressとdhcp-rangeが変更前の172.からのアドレスだったのでコケたぽい。
そして、iptablesを設定してから気づいたが、listen-addressは設定してるとNAT設定したあとにまた起動時にdnsmasq がエラー吐いた。
コメントアウトした。
DNS機能はなしでDHCPだけにすることはできないのかな?

iptablesの設定はかなりハマったが、
/etc/systemd/system/armbian-restore-iptables.service が起動時に /etc/iptables.ipv4.nat を読み込むみたい。
なので、iptablesをいじったあとは、
$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
で保存されて再起動後も有効になるぽい。
調べてたら iptables-persistent を入れて/etc/iptables/rules.v4 に保存するみたいな情報が散乱してたが、
iptables-save は最初から入ってて、/etc/iptables/rules.v4は起動時に読み込まれない。

iptablesの設定は、
$ sudo iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
1行だけ。
設定してから上のコマンドで保存すれば再起動後も有効。
-t nat がnatテーブルの指定。
-A POSTROUTING がPOSTROUTINGチェインに追加。
-s 192.168.1.0/24 が送信元アドレス。
-o eth0が転送先インターフェイス。
-j MASQUERADE が処理内容。
で、Androidスマホで確認したが192.168.1.0/24の範囲からの通信をグローバルに出れるインターフェイスに転送された。