ラズベリーパイ2
FreeBSD
WEBサーバ構築の準備
2016年
9月23日
現在のAT互換機で稼働している自宅サーバをラズベリーパイ2で稼働させるために調査を開始しました。CARP/HASTを使って2重化が最終目標ですが、はじめは普通の単体で稼働させます。配布されているラズベリーパイ用のイメージを使うと当然ながら2次記憶はSDカードです。普通に量販店などで売られているSDカードに頻繁に書き込むと直ぐに書き込み回数の上限に達してしまう可能性があります。各種ログが書き込まれる/verは問題になりそうです。/tmpはtmpfsなのでRAM上に作られて問題ないです。Linux系のラズベリーパイでは外付けHDDからブートさせることができるようですが、FreeBSDの場合を調べてみます。FreeBSDでは初めにu−bootが立ち上がり、その後ubldrに制御が移ります。これらのブートローダのイメージはいずれもSDカード上にあります。これらのブートローダがUSBに接続した外付けHDDを認識できれば、そこからブートさせられる可能性があります。
まず、u−bootです。
U-Boot 2015.04 (Aug 05 2016 - 13:46:54) // <- 11.0のベータ4に付いているu−boot
DRAM: 944 MiB
WARNING: Caches not enabled
RPI 2 Model B
MMC: bcm2835_sdhci: 0
reading uboot.env
** Unable to read "uboot.env" from mmc0:1 **
Using default environment
In: serial
Out: lcd
Err: lcd
Net: Net Initialization Skipped
No ethernet found.
Hit any key to stop autoboot: 2 // <-2,1,0とカウントダウンしてくので任意のキーを押して
// 自動起動を停止させます。
U-Boot> help // <-helpとキーインするとu−bootで使えるコマンドが表示されます。
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
bmp - manipulate BMP image data
boot - boot default, i.e., run 'bootcmd'
・
・ 中略
・
tftpboot- boot image via network using TFTP protocol
true - do nothing, successfully
usb - USB
sub-system
// <-usbコマンドがあります。
usbboot - boot from USB
device
// <-usbbootコマンドがあります。
version - print monitor, compiler and linker version
U-Boot> help usb // <-help usbとキーインするとusbのコマンドが表示されます。
usb - USB sub-system
Usage:
usb start - start (scan) USB controller
usb reset - reset (rescan) USB controller
usb stop [f] - stop USB [f]=force stop
usb tree - show USB device tree
usb info [dev] - show available USB devices
usb test [dev] [port] [mode] - set USB 2.0 test mode
(specify port 0 to indicate the device's upstream port)
Available modes: J, K, S[E0_NAK], P[acket], F[orce_Enable]
usb storage - show details of USB storage devices
usb dev [dev] - show or set current USB storage device
usb part [dev] - print partition table of one or all USB storage devices
usb read addr blk# cnt - read `cnt' blocks starting at block `blk#'
to memory address `addr'
usb write addr blk# cnt - write `cnt' blocks starting at block `blk#'
from memory address `addr'
U-Boot> usb info // <-USBメモリを挿して、再立ち上げ、USBの情報を表示します。
1: Hub, USB Revision 1.10
- U-Boot Root Hub
- Class: Hub
- PacketSize: 8 Configurations: 1
- Vendor: 0x0000 Product 0x0000 Version 0.0
Configuration: 1
- Interfaces: 1 Self Powered 0mA
Interface: 0
- Alternate Setting 0, Endpoints: 1
- Class Hub
- Endpoint 1 In Interrupt MaxPacket 2 Interval 255ms // <-HUBしか見つかりません。
U-Boot> usb reset // <-USBバスを再スキャンします。
resetting USB...
USB0: Core Release: 2.80a
scanning bus 0 for devices... submit_control_msg: Error (HCINT=00000082) // <-エラーです。
unable to get device descriptor (error=-1)
1 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found // <-認識してくれません。
scanning usb for ethernet devices... 0 Ethernet Device(s) found
因みに、mmcは
U-Boot> mmc info // <-mmcの情報を表示します。
Device: bcm2835_sdhci
Manufacturer ID: 2
OEM: 544d
Name: SA32G
Tran Speed: 50000000
Rd Block Len: 512
SD version 3.0
High Capacity: Yes
Capacity: 28.9 GiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes
U-Boot> mmc dev // <-mmcのデバイスを表示します。
switch to partitions #0, OK
mmc0 is current device // <-mmc0がカレントデバイスです。
U-Boot> fatls mmc 0 // <-先頭はFATなのでfatlsコマンドでファイルを表示できます。
17900 bootcode.bin
103 config.txt
6161 fixup.dat
2366 fixup_cd.dat
9214 fixup_x.dat
2664088 start.elf
567672 start_cd.elf
3621768 start_x.elf
301136 u-boot.bin
271821 ubldr
223912 ubldr.bin
9349 rpi2.dtb
12 file(s), 0 dir(s)
残念ながら、11.0のベータ4に付属のu−bootはUSBは扱えないようです。
イーサはどうでしょうか?
U-Boot> tftpboot // <-tftpを実行してみます。
No ethernet found.
U-Boot> mii device // <-phyデバイス表示します。
MII devices:
U-Boot> mii info // <-phyをスキャンしてみます。
NULL device name!
No such device: <NULL>
・
・ 中略
・
NULL device name!
No such device: <NULL>
イーサも実装されていなようです。
今後のためにブート時のパラメータを調べておきます。
U-Boot> print // <-変数を表示します。
Fatboot=env exists loaderdev || env set loaderdev ${fatdev}; env exists UserFatboot && run UserFatboot; echo Booting from: ${fatdev} ${bootfile}; fatload ${fatdev} ${loadaddr} ${bootfile} && bootelf ${loadaddr};
Netboot=env exists ethact || usb start; env exists loaderdev || env set
loaderdev net; env exists UserNetboot && run UserNetboot; dhcp
${loadaddr} ${bootfile} && bootelf ${loadaddr};
SetupFatdev=env exists fatdev || env set fatdev 'mmc 0';
arch=arm
baudrate=115200
board=rpi_2
board_name=rpi_2
bootcmd=run Fatboot // <-ブートのコマンドはFatbootです。
bootdelay=2
bootfile=ubldr // <-Fatbootで使っている変数です。
cpu=armv7
fatdev=mmc 0 // <-Fatbootで使っている変数です。
fdtaddr=0x100
fdtfile=bcm2836-rpi-2-b.dtb
kernel_addr_r=0x01000000
loadaddr=0x02000000 // <-Fatbootで使っている変数です。
preboot=fdt
addr 0x100; env exists bootfile || env set bootfile ubldr; env exists
SetupFatdev && run SetupFatdev; env exists UserPreboot
&& run UserPreboot;
pxefile_addr_r=0x00100000
ramdisk_addr_r=0x02100000
scriptaddr=0x00000000
soc=bcm283x
stderr=serial,lcd
stdin=serial,lcd
stdout=serial,lcd
usbethaddr=b8:27:eb:45:3a:f7
vendor=raspberrypi
Environment size: 1064/16380 bytes
変数を代入すると、Fatbootは以下のように展開されます。
Fatboot=
env exists loaderdev || env set loaderdev mmc 0;
env exists UserFatboot && run UserFatboot;
echo Booting from:mmc 0 ubldr;
fatload mmc 0 0x02000000 ubldr && bootelf 0x02000000;
ここでu−bootのコマンドについて
コマンドが成功すると終了ステータス0、そうでなければ終了ステータス1を返します。
コマンドの連結は
コマンド1 && コマンド2
コマンド1の終了ステータスが0(成功)の場合、コマンド2を実行します。
コマンド1 || コマンド2
コマンド1の終了ステータスが0以外(成功以外)の場合、コマンド2を実行します。
Fatbootの解析
Fatboot=
env exists loaderdev || env set loaderdev mmc 0;
// 変数loaderdevが無ければ変数loaderdevをmmc 0に設定
env exists UserFatboot && run UserFatboot;
// 変数UserFatbootがあればUserFatbootを実行
echo Booting from: mmc 0 ubldr;
// "Booting from: mmc 0 ubldr"を表示
fatload mmc 0 0x02000000 ubldr && bootelf 0x02000000;
// fatload mmc 0 0x02000000 ubldrを実行、成功したら、booteld 0x02000000を実行
続いてubldrです。
Booting from: mmc 0 ubldr
reading ubldr
271821 bytes read in 204 ms (1.3 MiB/s)
## Starting application at 0x02000098 ...
Consoles: U-Boot console
Compatible U-Boot API signature found @0x3ab4a4c8
FreeBSD/armv6 U-Boot loader, Revision 1.2
(root@releng2.nyi.freebsd.org, Fri Aug 5 14:01:56 UTC 2016)
DRAM: 944MB
Number of U-Boot devices: 1
U-Boot env: loaderdev='mmc 0'
Found U-Boot device: disk
Checking unit=0 slice=<auto> partition=<auto>... good.
Booting from disk0s2a:
/boot/kernel/kernel data=0x729e64+0x17a19c syms=[0x4+0x7de90+0x4+0x90a5a]
Hit [Enter] to boot immediately, or any other key for command prompt.
// <-ここでスペースキーを押して自動起動を停止させます。
Type '?' for a list of commands, 'help' for more detailed help.
loader> ? // <-コマンドリストを表示してみます。
Available commands:
boot boot a file or loaded kernel
autoboot boot automatically after a delay
help detailed help
? list commands
show show variable(s)
set set a variable
unset unset a variable
echo echo arguments
read read input from the terminal
more show contents of a file
lsdev list all devices // <-デバイス表示コマンドがあります。
include read commands from a file
ls list files
load load a kernel or module
load_geli load a geli key
unload unload all modules
lsmod list loaded modules
heap show heap usage
reboot reboot the system
devinfo show U-Boot devices
sysinfo show U-Boot system info
ubenv show or import U-Boot env vars
fdt flattened device tree handling
boot-conf load kernel and modules, then autoboot
read-conf read a configuration file
enable-module enable loading of a module
disable-module disable loading of a module
toggle-module toggle loading of a module
show-module show module load data
try-include try to load/interpret files
loader> lsdev // <-デバイス表示コマンドを実行します。
disk devices:
disk0 (MMC) // <-当然ですが、MMCが見つかります。
disk0s1: DOS/Windows
disk0s2: FreeBSD
disk0s2a: FreeBSD UFS
net devices:
net0: // <-イーサもあるようです。
<<FreeBSDブートプロセスまとめ>>
カッコ内は実行プロセッサと実行メモリ、対象メディア
Soc_rom - Zero stage boot(GPU_RISC)(ROM)(SDcard)
bootcode.bin - First stage boot(GPU_RISC)(L2cache)(SDcard)
start.elf - Second stage boot(GPU_RISC)(SDRAM)(SDcard)
uboot.bin - Third stage: U-Boot loader(ARM)(SDRAM)(SDcard)
ubldr - Fourth stage: FreeBSD bootloader(ARM)(SDRAM)(SDcard/Net)
5つのブートローダが動いていてFreeBSDのカーネルが立ち上がります。
<<Linuxのブートプロセスまとめ>>
Raspberry Piのブートプロセスメモを参照に〜
カッコ内は実行プロセッサと対象メディア
Soc_rom - Zero stage boot(GPU_RISC)(ROM)(SDcard)
bootcode.bin - First stage boot(GPU_RISC)(L2cache)(SDcard)
start.elf - Second stage boot(GPU_RISC)(SDRAM)(SDcard)
kernel.img - Linux kernel(ARM)(SDRAM)(何でも)
<<現状まとめ>>
LinuxでUSBの外部HDDからブートできるのはstart.elfからカーネルが呼ばれるからのようです。一方、FreeBSDではu−boot、rubldrはMMCからブートをメインに作られているようで、外付けUSBからブートするのは難しそうです。因みにu−bootはコンフィギュレーションを変えればUSBにアクセスが可能です。
<</varのみ外付けHDDに移動>>
ファイルシステム全体を外付けHDDにするのは現状、難しそうなので/varのみ外付けHDDに移動してみます。手持ちに20GのPATAのHDDが複数あったので、ヤフオクで2.5インチのUSB変換ケースを購入しました。難点は付属の二又ケーブルで別に電源用のUSBポートが必要なこと(笑)。電源ポートはACアダプタに接続しました。
Linuxですが、ここを参考に/varのみ外付けHDDに移動してみます。ブート時にHDDの認識が間に合わなとマウントに失敗するので、以下のように少し待つように設定します。取りあえず、FATのまま実験します。
以下、shutdown nowでシングルユーザモードに移行した後で以下を実行します。
# cd /mnt
# mkdir vstorage
# mount -t msdosfs /dev/da0s1 /mnt/vstorage
# cd /var
# cp -av /var /mnt/vstorage
# mv /var /var.old
# cd /
# ln -s /mnt/vstorage/var /var
/boot/loader.confに以下を追加してウエイトを追加します。
kern.cam.boot_delay=10000
/etc/fstabに以下を追加し自動的にマウントします。
/dev/da0s1 /mnt/tstorage msdosfs rw 2 2
リブートして/varが外付けHDDになっているか確認します。問題無いようです。とりあえずFATで実験しましたが、実際にはufsで使う予定です。
9月26日
実際の運用のためにFATからufsに変更しましたが、せっかくなのでUUIDを使ってみます。/varを元に戻してシングルユーザモードに移行し、ここやここを参考にします。
# cd /
# umount /dev/da0
# gpart show da0
=> 63 39070017 da0 MBR (19G)
63
1985 - free - (993K)
2048 39065600 1 !12 (19G)
39067648 2432 - free - (1.2M)
# gpart delete -i 1 da0 // <-一旦、削除します。
da0s1 deleted
# gpart destroy da0 // <-そして、壊します。
da0 destroyed
# gpart create -s GPT da0 // <-新たに生成します。
da0 created
# gpart show da0 // <-確認します。
=> 40 39070000 da0 GPT (19G)
40 39070000 - free - (19G)
# gpart add -t freebsd-ufs da0 // <-ufsを追加します。
da0p1 added
s
# gpart show da0 // <-確認します。
=> 40 39070000 da0 GPT (19G)
40 39070000 1 freebsd-ufs (19G) // <-ufsになりました。
# ls /dev/da0*
/dev/da0 /dev/da0p1 // <-このパーティションです。
# newfs -U /dev/da0p1 // <-ファイルシステムを作ります。
/dev/da0p1: 19077.2MB (39070080 sectors) block size 32768, fragment size 4096
using 31 cylinder groups of 626.09MB, 20035 blks, 80256 inodes.
with soft updates
super-block backups (for fsck_ffs -b #) at:
192, 1282432, 2564672, 3846912, 5129152, 6411392, 7693632, 8975872, 10258112,
11540352, 12822592, 14104832, 15387072, 16669312, 17951552, 19233792,
20516032, 21798272, 23080512, 24362752, 25644992, 26927232, 28209472,
29491712, 30773952, 32056192, 33338432, 34620672, 35902912, 37185152, 38467392
# gpart list da0 // <-UUIDを確認します。
Geom name: da0
modified: false
state: OK
fwheads: 255
fwsectors: 63
last: 39070039
first: 40
entries: 152
scheme: GPT
Providers:
1. Name: da0p1
Mediasize: 20003840000 (19G)
Sectorsize: 512
Stripesize: 0
Stripeoffset: 20480
Mode: r1w1e2
rawuuid: f1b8f0af-637d-11e6-80a7-b827eb453af7 // <-これがUUIDです。
rawtype: 516e7cb6-6ecf-11d6-8ff8-00022d09712b // <-これはGUIDです。
label: (null)
length: 20003840000
offset: 20480
type: freebsd-ufs
index: 1
end: 39070039
start: 40
Consumers:
1. Name: da0
Mediasize: 20003880960 (19G)
Sectorsize: 512
Mode: r1w1e3
コピーとシンボリックリンクは同様にして、fstabを変更します。
# cat /etc/fstab // <-fstabを変更します。
# Custom /etc/fstab for FreeBSD embedded images
/dev/ufs/rootfs /
ufs rw
1 1
/dev/msdosfs/MSDOSBOOT /boot/msdos msdosfs rw,noatime 0 0
tmpfs /tmp tmpfs rw,mode=1777,size=50m 0 0
#/dev/hast/disk1 /hast/disk1 nullfs rw,noauto 0 0
#/dev/da0 /mnt/vtstorage ufs rw 2 2
/dev/gptid/f1b8f0af-637d-11e6-80a7-b827eb453af7 /mnt/vtstorage ufs rw 2 2 // <-上の1行の代りにUUIDを指定した1行を追加します。
リブートして/varがUUIDの外付けHDDになっているか確認します。問題無いようです。難点はmountやdfコマンドなどで出力が長くなり、80文字の端末のままだと折り返しになると。
# mount
/dev/ufs/rootfs on / (ufs, local, soft-updates)
devfs on /dev (devfs, local)
/dev/msdosfs/MSDOSBOOT on /boot/msdos (msdosfs, local, noatime)
tmpfs on /tmp (tmpfs, local)
/dev/gptid/f1b8f0af-637d-11e6-80a7-b827eb453af7 on /mnt/vtstorage (ufs, local, soft-updates)
# df
Filesystem
1K-blocks Used Avail Capacity
Mounted on
/dev/ufs/rootfs
29282268 818020 26121668 3% /
devfs
1
1 0
100% /dev
/dev/msdosfs/MSDOSBOOT
51128 7552 43576
15% /boot/msdos
tmpfs
51200 4
51196 0% /tmp
/dev/gptid/f1b8f0af-637d-11e6-80a7-b827eb453af7
18910932 376 17397684
0% /mnt/vtstorage