千石通商で処分品の箱にあったpcDuinoを買ってきたので、FreeBSDを試してみます。
こののターゲットはAllwinterのA10というSOCが使われています。我が家で初のarmv7系です。またまた一周遅れで自分らしいです。
Allwinnerのサポートは10Rで入ってA10は初期のターゲットだったようです。A10のターゲットはcubieboardというボードだったようです。
pcDuinoはCFIなFlashが実装されているようですが、Liteはパターンはあるけど実装されてなくて、SDからブートするようです。pcDuinoはSDからFlashにLinuxをコピーしてブートするようですが、Liteについては資料が見当たりませんでした。このため一旦Linuxを試そうと思ったのですがあきらめました。
このターゲットでFreeBSDを起動する方法は二つあり、u-bootから直接カーネルを起動する方法とu-bootからubldrを起動してそこからカーネルを起動する方法になります。
公式のimgは後者でつくられているのですが、ZRouterでのビルドを行うので、前者で試そうと思います。
まずはu-bootをSDに用意します。
手持ちのSDのGPTな設定がFreeBSDでは消せなかったので、MacでMBRのFATでフォーマットしてみました。(gpart destroy -F da0すればよかったみたいです)
% gpart show da0
=> 1 15661055 da0 MBR (7.5G)
1 1 - free - (512B)
2 15661054 1 fat32 (7.5G)
一旦FAT部分を消します。
% sudo gpart delete -i 1 da0
da0s1 deleted
% gpart show da0
=> 1 15661055 da0 MBR (7.5G)
1 15661055 - free - (7.5G)
splとu-bootを書き込みます。
% sudo pkg install u-boot-cubieboard
% cd /usr/local/share/u-boot/u-boot-cubieboard
% sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/da0 bs=1k seek=8 conv=sync
FAT部分を作ります。
% sudo gpart add -b 1m -s 24m -t '\!12' /dev/da0
da0s1 added
% sudo gpart set -a active -i 1 /dev/da0
active set on da0s1
% sudo newfs_msdos -L boot -F 16 /dev/da0s1
/dev/da0s1: 48992 sectors in 6124 FAT16 clusters (4096 bytes/cluster)
BytesPerSec=512 SecPerClust=8 ResSectors=1 FATs=2 RootDirEnts=512 Sectors=49077 Media=0xf0 FATsecs=24 SecPerTrack=63 Heads=255 HiddenSecs=0
本体にシリアル接続して115200でターミナルを上げて出来上がった、SDを差して起動します。
シリアル接続はここです。
起動すると以下のような表示がでます。HDMIにも表示は出ますが、入力はシリアルなので、ターミナルでオペレーションをするのがよいでしょう。
U-Boot SPL 2018.09 (Oct 26 2018 - 02:52:54 +0000)
DRAM: 512 MiB
CPU: 1008000000Hz, AXI/AHB/APB: 3/2/2
Trying to boot from MMC1
U-Boot 2018.09 (Oct 26 2018 - 02:52:54 +0000) Allwinner Technology
CPU: Allwinner A10 (SUN4I)
Model: Cubietech Cubieboard
I2C: ready
DRAM: 512 MiB
MMC: mmc@01c0f000: 0
Loading Environment from FAT... OK
HDMI connected: Setting up a 1920x1080 hdmi console (overscan 0x0)
In: serial
Out: vga
Err: vga
Net: eth0: ethernet@01c0b000
starting USB...
USB0: USB EHCI 1.00
USB1: USB OHCI 1.0
USB2: USB EHCI 1.00
USB3: USB OHCI 1.0
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 2 for devices... 1 USB Device(s) found
このターゲットはシリアルを接続しなおして起動しないと起動しませんでした。USBモジュールとの相性なのかもしれません。
ZRouterを使い先日13になったばかりのheadでカーネルをビルドできるように調整します。
カーネルがビルドできたら、エントリーアドレスを確認します。0xc0200180から0x40200180となります。
% readelf -h Pcduino_Lite_kernel | grep "Entry point address"
Entry point address: 0xc0200180
とりあえずブートしてみるが何も起こらない
=> fatload mmc 0 0x40200000 kernel; go 0x40200180
3728916 bytes read in 305 ms (11.7 MiB/s)
## Starting application at 0x40200180 ...
u-bootでuartの確認
=> mw.b 0x01c28000 0x55
U=>
locore-v6.Sに以下のコードを入れて確認
ldr r0,=0x01c28000
ldr r2,=0x55
strb r2, [r0]
実行は移っているみたい。
=> fatload mmc 0 0x40200000 kernel; go 0x40200180
3728916 bytes read in 305 ms (11.7 MiB/s)
## Starting application at 0x40200180 ...
U
未定義命令の.byte 0xFF, 0xFF, 0xFF, 0xFFを入れても確認できます。
## Starting application at 0x40200180 ...
undefined instruction
pc : [<40200180>] lr : [<5ef69777>]
reloc pc : [<2b299180>] lr : [<4a002777>]
sp : 5af3f098 ip : 5efb283c fp : 00000002
r10: 5efb5410 r9 : 5af46ed8 r8 : 5af5be78
r7 : 5ef6974d r6 : 00000002 r5 : 40200180 r4 : 5af5be7c
r3 : 40200180 r2 : 00000006 r1 : 5af5be7c r0 : 00000001
Flags: nZCv IRQs off FIQs off Mode SVC_32
Code: 00000000 00000000 00000000 00000000 (ffffffff)
Resetting CPU ...
resetting ...
とりあえずEARLY_PRINTFを使ってカーネルをビルドしてみます。
変わりません。。。~~コードを見るとbuild_pagetablesとbuild_device_pagetablesが同じ処理になっていて意味無く、壊れているっぽいです。~~問題は他のようです。
思ったより手こずるので、ビルドの度にSDに焼いてだと手間がかかるので、ネットワークで確認できるようにしてみた。2018.09のビルドのu-bootはネットワークがちゃんと使えました。
=> setenv ipaddr 10.10.10.111
=> setenv serverip 10.10.10.3
=> tftpboot 0x40200000 Pcduino_Lite_kernel
Using ethernet@01c0b000 device
TFTP from server 10.10.10.3; our IP address is 10.10.10.111
Filename 'Pcduino_Lite_kernel'.
Load address: 0x40200000
Loading: #################################################################
#################################################################
#################################################################
############################################################
599.6 KiB/s
done
Bytes transferred = 3729184 (38e720 hex)
=> go 0x40200180
## Starting application at 0x40200180 ...
試しに11.2RのimgをSDに焼いてみたのですが起動しません。。。
U-Boot SPL 2018.03 (Jun 22 2018 - 00:42:02 +0000)
DRAM: 512 MiB
CPU: 1008000000Hz, AXI/AHB/APB: 3/2/2
Trying to boot from MMC1
U-Boot 2018.03 (Jun 22 2018 - 00:42:02 +0000) Allwinner Technology
CPU: Allwinner A10 (SUN4I)
Model: Cubietech Cubieboard
I2C: ready
DRAM: 512 MiB
MMC: SUNXI SD/MMC: 0
Loading Environment from FAT... *** Warning - bad CRC, using default environment
Failed (-5)
Loading Environment from MMC... *** Warning - bad CRC, using default environment
Failed (-5)
HDMI connected: Setting up a 1920x1080 hdmi console (overscan 0x0)
In: serial
Out: vga
Err: vga
SCSI: AHCI PHY power up failed.
Net: eth0: ethernet@01c0b000
starting USB...
USB0: USB EHCI 1.00
USB1: USB OHCI 1.0
USB2: USB EHCI 1.00
USB3: USB OHCI 1.0
scanning bus 0 for devices... 1 USB Device(s) found
scanning bus 2 for devices... 1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot: 0
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot.scr
199 bytes read in 13 ms (14.6 KiB/s)
## Executing script at 43100000
235476 bytes read in 42 ms (5.3 MiB/s)
## Starting application at 0x42000000 ...
Consoles: U-Boot console
Compatible U-Boot API signature found @0x5af4d3c0
FreeBSD/armv6 U-Boot loader, Revision 1.2
(Fri Jun 22 01:54:49 UTC 2018 root@releng2.nyi.freebsd.org)
DRAM: 512MB
MMC Device 1 not found
MMC Device 2 not found
MMC Device 3 not found
Number of U-Boot devices: 1
U-Boot env: loaderdev not set, will probe all devices.
Found U-Boot device: disk
Probing all disk devices...
Checking unit=0 slice=<auto> partition=<auto>... good.
Booting from disk0s2a:
Loading /boot/defaults/loader.conf
/boot/kernel/kernel data=0x63932c+0x4acd4 syms=[0x4+0x6b630+0x4+0x9a638]
-
Hit [Enter] to boot immediately, or any other key for command prompt.
Booting [/boot/kernel/kernel]...
No valid device tree blob found!
Type '?' for a list of commands, 'help' for more detailed help.
loader>
13-CURRENTのスナップショットのimgはkernelは起動しますがパニックしました。
いろいろ試したところ、mapしてuartに書けるようになりました。
uint8_t *tx = (uint8_t *)0xf1c28000;
*tx = '1';
これで確認したら、OF_install()がエラーを起こしているようです。
OF_install()はdev/ofw/openfirm.cにあって、引数のofw_fdtというkbojを探すようです。
OFW_DEF()というマクロでofw_fdtがofw_setにセットされるようで、それを探しに行くのが本来の流れのようです。
初期のarmのブートの話はここに書いてありました。
OF_install()を逆アセンブルするとこんな風です。
c0236e4c: e30175d4 movw r7, #5588 ; 0x15d4
c0236e50: e30145d0 movw r4, #5584 ; 0x15d0
c0236e54: e3a08000 mov r8, #0 ; 0x0
c0236e58: e34c7046 movt r7, #49222 ; 0xc046
c0236e5c: e34c4046 movt r4, #49222 ; 0xc046
c0236e60: e1540007 cmp r4, r7
c0236e64: 2a000023 bcs c0236ef8 <OF_install+0xc8>
c0236e68: e3085000 movw r5, #32768 ; 0x8000
c0236e6c: e34f51c2 movt r5, #61890 ; 0xf1c2
c0236e70: e5949000 ldr r9, [r4]
c0236e74: e5990000 ldr r0, [r9]
c0236e78: e3500000 cmp r0, #0 ; 0x0
c0236e7c: 0a00000d beq c0236eb8 <OF_install+0x88>
c0236e80: e5d00000 ldrb r0, [r0]
c0236e84: e5c50000 strb r0, [r5]
c0236e88: e5990000 ldr r0, [r9]
c0236e8c: e3500000 cmp r0, #0 ; 0x0
c0236e90: 0a000008 beq c0236eb8 <OF_install+0x88>
c0236e94: e1a01006 mov r1, r6
c0236e98: eb04d9a7 bl c036d53c <strcmp>
readelfで見るとこんな風です。
% readelf -a Pcduino_Lite_kernel | grep _set_ofw_set
2393: c04615d4 0 NOTYPE GLOBAL DEFAULT 6 __stop_set_ofw_set
6355: c04615d0 0 NOTYPE GLOBAL DEFAULT 6 __start_set_ofw_set
1015: c04615d0 4 OBJECT LOCAL DEFAULT 6 __set_ofw_set_sym_ofw_fdt
11402: c04615d0 0 NOTYPE GLOBAL DEFAULT 6 __start_set_ofw_set
11403: c04615d4 0 NOTYPE GLOBAL DEFAULT 6 __stop_set_ofw_set
中身はこんなです。
c04615d0 <__start_set_ofw_set>:
c04615d0: c04d1c4c subgt r1, sp, ip, asr #24
Disassembly of section set_uart_fdt_class_and_device_set:
c04615d4 <__start_set_uart_fdt_class_and_device_set>:
c04615d4: c04d2804 subgt r2, sp, r4, lsl #16
Disassembly of section set_uart_fdt_class_set:
ちゃんと__start_set_ofw_setを参照しているように見れます。
その先はこんなです。
c04d1c4c <ofw_fdt>:
c04d1c4c: c0440595 umaalgt r0, r4, r5, r5
c04d1c50: c0459028 subgt r9, r5, r8, lsr #32
...
コードはこんなです。
static ofw_def_t ofw_fdt = {
OFW_FDT,
ofw_fdt_methods,
0
};
OFW_DEF(ofw_fdt);
c0440595-c0200000なアドレスに実態はあるように見えます。
% hexdump -c Pcduino_Lite_kernel | grep ^0240590
0240590 r t y \n \0 o f w _ f d t \0 d t b
u-bootでロードすると確かにofw_fdtの実態が空になる。なんでかな。
=> md 0x40236e4c 4
40236e4c: e30175d4 e30145d0 e3a08000 e34c7046 .u...E......FpL.
=> md 0x404615d0 4
404615d0: c04d1c4c c04d2804 c04d284c c04d2978 L.M..(M.L(M.x)M.
=> md 0x404d1c4c 4
404d1c4c: 00000000 00000000 00000000 00000000 ................
kbinをロードしても同じ。
=> tftpboot 0x40200180 Pcduino_Lite_kernel.kbin
c04d1c4c(02d1c4c)にあるべきものがELFだと02d0c4cにあるようだ。ELFを理解してロードしなければちゃんと実行できないのかも。
% readelf -S Pcduino_Lite_kernel | grep '\.data'
[19] .data PROGBITS c04c7a00 2c6a00 0324d4 00 WA 0 0 64
で
Disassembly of section .data:
c04c7a00 <esym>:
c04c7a00: c054c000 subsgt ip, r4, r0
% hexdump Pcduino_Lite_kernel.kbin | grep "c000 c054"
027f7e0 0104 0000 0012 0001 00a1 0000 c000 c054
028a790 01ac 0000 0012 0001 9d81 0001 c000 c054
02c6880 c000 c054 0024 0000 0000 0000 f8e9 3454
最後の行がそれなんだが02c6880+180で02c6a00なんでやっぱずれます。
FreeBSDでは11くらいで、objcopyを従来のbinutilsのobjcopyからBSDライセンスのelftoolchainのelfcopyに変更しました。
pkgでarm-elf-binutilsをインストールしてこちらのobjcopyを使ったら、上記の問題は解決しました。
objcopy(elfcopy)の不具合レポートMLに送っておこうと思います。
リンカースクリプトによってELFのままでも起動できたりobjcopyしたものが起動できますが、アドレスの間違いなどがあるかもしれないので、u-bootイメージが一番問題なく起動できる気がします。
=> tftp 0x41000000 Pcduino_Lite_kernel.kbin.gz.uboot
=> bootm
initarm()のpmap_bootstrap_prepare(lastaddr)で落ちるのですが、原因がわからないのでとりあえずしばらく放置します。
armv7はメジャーなターゲットだと思うのですが、いろいろな人が手を入れて複雑になってしまって、いばらの道になってしまっているような感じがあります。
あとAllwinnerのサポートは当初A10などをターゲットにしたコードがあったようですが、次々チップが増えてそのコードを継ぎ足し継ぎ足ししたので、ちょと汚くなってる感じがします。
12.0-RC1のimageを試してみましたが、起動はしますが、途中でとまります。
...
Starting file system checks:
/dev/ufs/rootfs: FILE SYSTEM CLEAN; SKIPPING CHECKS
/dev/ufs/rootfs: clean, 1518467 free (75 frags, 189799 blocks, 0.0% fragmentation)