ラズベリーパイ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−bootUSBは扱えないようです。


イーサ
はどうでしょうか?

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の終了ステータスが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−bootrubldrはMMCからブートをメインに作られているようで、外付けUSBからブートするのは難しそうです。因みにu−bootはコンフィギュレーションを変えればUSBにアクセスが可能です。


<</varのみ外付けHDDに移動>>
ファイルシステム全体を外付けHDDにするのは現状、難しそうなので/varのみ外付けHDDに移動してみます。手持ちに20GPATAHDDが複数あったので、ヤフオクで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

# 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行を追加します。

リブートして/varUUIDの外付けHDDになっているか確認します。問題無いようです。難点はmountdfコマンドなどで出力が長くなり、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

back



line