1

Тема: Установка FreeBSD на Netgear Stora с поддержкой ZFS

Недавно мне понадобилось сделать резервную файловую хранилку для бекапов, максимально дешево, минимум на 2 диска. Прошерстив барахолки, выбор пал на Netgear Stora и в итоге был куплен за 2000 р. Изначально не было планов на него что-то ставить, но прошивка оказалась на редкость дурацкая - сбросить пароль и настройки на дефолт у меня так и не вышло... После чего твердо решил поставить на этот девайс что-то другое.

Почему FreeBSD а не Debian Linux? Ответа на этот вопрос не будет. Потому что, вот так. Just for fun, как говорится. Да и просто было интересно попробовать FreeBSD на ARM и особенно попытаться поднять ZFS. Не смотря на устрашающую ссылку в FAQ "For unix guru only", все оказалось не так уж сложно и задача была выполнена. ZFS тоже работает, но со скрипом - все же 128 Мб ОЗУ чрезвычайно мало и в окончательном варианте я от ZFS отказался.

Первое что необходимо - TTL-кабель. Что это, где его взять и как подключить - подробно описано в других ветках по установке Дебиана и я на этом останавливаться не буду. По ходу описания, чтобы различать где какие команды вводить, условимся так:

i386# - консоль x86-системы
stora# - консоль Netgear Stora
Marvell>> - консоль загрузчика U-boot

Краткий план действий:
1) Получение исходников системы
2) Сборка мира и ядра
3) Настройка TFTP-, DHCP- и NFS-сервера
4) Загрузка системы через TFTP и NFS
5) Перенос системы на HDD
Дополнительно:
6) Перенос системы во внутренний NAND Flash
7) Аппаратное ускорение шифрования
8) Шифрование дисков
9) Поддержка ZFS


1) Нужна система с уже установленной и работающей FreeBSD, рекомендую не ниже 10.x версии, но это не обязательно. Как установить на ПК - описывать тут не буду, этих статей достаточно. На Stora будем ставить текущую ветку, которая еще находится в разработке - т.е. 11-CURRENT. 

i386# mkdir /usr/src11
i386# cd /usr/src11

Получаем исходники системы:

i386# svnlite co svn://svn.freebsd.org/base/head /usr/src11

(В FreeBSD 9.x и старше этого пакета в системе нет, svn нужно предварительно установить)


2) Чтобы не собирать из исходников множество лишнего софта и библиотек, убираем лишнее и добавляем поддержку NAND Flash.

i386# ee /etc/src.conf

Добавляем строки:

WITH_NAND=YES
WITHOUT_AUDIT=YES
WITHOUT_AUTHPF=YES
WITHOUT_ACCT=YES
WITHOUT_ACPI=YES
WITHOUT_AMD=YES
WITHOUT_APM=YES
WITHOUT_ASSERT_DEBUG=YES
WITHOUT_ATM=YES
WITHOUT_BLUETOOTH=YES
WITHOUT_CALENDAR=YES
WITHOUT_CASPER=YES
WITHOUT_CAPSICUM=YES
WITHOUT_CDDL=YES
WITHOUT_CTF=YES
WITHOUT_DICT=YES
WITHOUT_EXAMPLES=YES
WITHOUT_FLOPPY=YES
WITHOUT_FREEBSD_UPDATE=YES
WITHOUT_GAMES=YES
WITHOUT_HTML=YES
WITHOUT_HYPERV=YES
WITHOUT_INET6=YES
WITHOUT_INET6_SUPPORT=YES
WITHOUT_IPFILTER=YES
WITHOUT_IPFW=YES
WITHOUT_IPX=YES
WITHOUT_IPX_SUPPORT=YES
WITHOUT_JAIL=YES
WITHOUT_KERBEROS=YES
WITHOUT_KERBEROS_SUPPORT=YES
WITHOUT_LIB32=YES
WITHOUT_LPR=YES
WITHOUT_MAIL=YES
WITHOUT_MAN=YES
WITHOUT_NCP=YES
WITHOUT_NETGRAPH=YES
WITHOUT_NETGRAPH_SUPPORT=YES
WITHOUT_NDIS=YES
WITHOUT_PC_SYSINSTALL=YES
WITHOUT_PF=YES
WITHOUT_PPP=YES
WITHOUT_QUOTAS=YES
WITHOUT_RESCUE=YES
WITHOUT_ROUTED=YES
WITHOUT_SENDMAIL=YES
WITHOUT_SHAREDOCS=YES
WITHOUT_SOURCELESS=YES
WITHOUT_SOURCELESS_HOST=YES
WITHOUT_SOURCELESS_UCODE=YES
WITHOUT_SSP=YES
WITHOUT_SYSINSTALL=YES
WITHOUT_WIRELESS=YES
WITHOUT_WIRELESS_SUPPORT=YES
WITHOUT_WPA_SUPPLICANT_EAPOL=YES
WITHOUT_X11=YES
WITHOUT_ZFS=YES

Тут можно добавить или удалить еще что-то по своему вкусу. Что значит каждая опция можно узнать в man src.conf.


2.1) Собираем мир. Опция -j4 задает кол-во потоков, на многоядерных системах можно увеличить. Процесс небыстрый, ждем. Убеждаемся, что сборка закончилась без ошибок.

i386# make -j4 buildworld TARGET_ARCH=arm
...
...
>>> World build completed .....

2.2) Ядро будем собирать свое, т.к. общий конфиг для устройств на Marvell Kirkwood содержит много лишнего. Конфиги ядра лежат в /usr/src11/sys/arm/conf.
Создаем свой конфиг:

i386# ee /usr/src11/sys/arm/conf/STORA-NFS

Сначала нам в любом случае понадобится ядро с поддержкой NFS. Конфиг ядра:

ident           STORA-NFS

include         "../mv/kirkwood/std.db88f6xxx"
options         SOC_MV_KIRKWOOD

# Перечислены опции, которые нужно собрать отдельными модулями, должно быть одной строкой
makeoptions     MODULES_OVERRIDE="crypto nfscommon nfslock nfssvc nfsd nfscl nand nandfs geom/geom_zero geom/geom_eli geom/geom_mbr tmpfs nullfs procfs md usb/uplcom"
makeoptions     WERROR="-Werror"

options         SCHED_4BSD              # Планировщик, нужен
options         GEOM_PART_GPT           # GPT-разметка
options         GEOM_LABEL              # Дисковые метки
options         FFS                    # UFS
options         SOFTUPDATES             # Softupdates в FFS

options         SYSVSHM                 # SYSV-style shared memory
options         SYSVMSG                 # SYSV-style message queues
options         SYSVSEM                 # SYSV-style semaphores
options         _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time extensions
options         MUTEX_NOINLINE
options         RWLOCK_NOINLINE
options         SX_NOINLINE
options         NO_FFS_SNAPSHOT
options         NO_SWAPPING

# Pseudo devices
device          loop
device          random

# Serial ports
device          uart

# Networking
device          ether
device          mge
device          mii
device          e1000phy
device          bpf
options         INET
options         TCP_OFFLOAD

# SATA
device          mvs
device          ahci
device          scbus
device          pass

# USB
device          usb
device          ehci
device          umass
device          da

# NAND flash
device          nand

# Flattened Device Tree
device          fdt
options         FDT
options         FDT_DTB_STATIC
makeoptions     FDT_DTS_FILE=stora.dts

# Включаем эти опции для загрузки через DHCP и NFS
options         NFSCL                   # NFS Client
options         NFSLOCKD                # Network Lock Manager
options         NFS_ROOT                # NFS-root
options         BOOTP                   # Поддержка BOOTP
options         BOOTP_NFSROOT           
options         BOOTP_NFSV3
options         BOOTP_WIRED_TO=mge0

Если планируется подключать различные USB-устройства типа wi-fi адаптеров или 3G-модемов, их нужно тоже добавить список MODULES_OVERRIDE, есть поддержка многих устройств, можно посмотреть в конфиге DREAMPLUG-1001, например.



2.3) Конфиг Flattened Device Tree. Чтобы не углубляться в детали, вкратце. В подобных девайсах обычно нет BIOS, как в больших ПК, поэтому все устройства, их адресация и прерывания задаются заранее в FDT-файле. файл указывается в конфиге ядра и затем ядро собирается с уже определенными устройствами. Выше в конфиге мы указали опцию FDT_DTS_FILE=stora.dts, это оно и есть.

Конфиг FDT должен лежать в директории /usr/src11/sys/boot/fdt/dts/arm/
Там есть общий шаблон для устройств на Marvell Kirkwood, но тут не все так просто, т.к. различные девайсы имеют разное кол-во ОЗУ, разметку флэш-памяти и т.д. С этим пришлось повозиться, подбирая значения экспериментально. Не все удалось настроить, в частности управление светодиодами не работает, аппаратное шифрование глючит (об этом ниже), поэтому все неработающее удалено. В результате вышел такой конфиг stora.dts:

/dts-v1/;

/ {
        model = "mrvl,DB-88F6281";
        compatible = "DB-88F6281-BP", "DB-88F6281-BP-A";
        #address-cells = <1>;
        #size-cells = <1>;

        aliases {
                ethernet0 = &enet0;
                mpp = &MPP;
                serial0 = &serial0;
                serial1 = &serial1;
                soc = &SOC;
                sram = &SRAM;
        };

        cpus {
                #address-cells = <1>;
                #size-cells = <0>;

                cpu@0 {
                        device_type = "cpu";
                        compatible = "ARM,88FR131";
                        reg = <0x0>;
                        d-cache-line-size = <32>;       // 32 bytes
                        i-cache-line-size = <32>;       // 32 bytes
                        d-cache-size = <0x4000>;        // L1, 16K
                        i-cache-size = <0x4000>;        // L1, 16K
                        timebase-frequency = <0>;
                        bus-frequency = <0>;
                        clock-frequency = <0>;
                };
        };

        memory {
                device_type = "memory";
                reg = <0x0 0x8000000>;          // 128M at 0x0
        };

        localbus@0 {
                #address-cells = <2>;
                #size-cells = <1>;
                compatible = "mrvl,lbc";
                bank-count = <3>;

                /* This reflects CPU decode windows setup. */
                ranges = <0x0 0x2f 0xf9300000 0x00100000>;

                nand@0,0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "mrvl,nfc";
                        reg = <0x0 0x0 0x00100000>;
                        bank-width = <2>;
                        device-width = <1>;

                        slice@0 {
                                reg = <0x0 0x100000>;
                                label = "uboot";
                                read-only;
                        };

                        slice@100000 {
                                reg = <0x100000 0x400000>;
                                label = "kernel";
                        };

                        slice@500000 {
                                reg = <0x500000 0x0fa00000>;
                                label = "root";
                        };
                };
        };

        SOC: soc88f6281@f1000000 {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "simple-bus";
                ranges = <0x0 0xf1000000 0x00100000>;
                bus-frequency = <0>;

                PIC: pic@20200 {
                        interrupt-controller;
                        #address-cells = <0>;
                        #interrupt-cells = <1>;
                        reg = <0x20200 0x3c>;
                        compatible = "mrvl,pic";
                };

                timer@20300 {
                        compatible = "mrvl,timer";
                        reg = <0x20300 0x30>;
                        interrupts = <1>;
                        interrupt-parent = <&PIC>;
                        mrvl,has-wdt;
                };

                MPP: mpp@10000 {
                        #pin-cells = <2>;
                        compatible = "mrvl,mpp";
                        reg = <0x10000 0x34>;
                        pin-count = <50>;
                        pin-map = <
                                 0 1            /* !MPP[ 0]:  SPI_SCn */
                                 1 1            /* !MPP[ 1]:  SPI_MOSI */
                                 2 1            /* !MPP[ 2]:  SPI_SCK */
                                 3 1            /* !MPP[ 3]:  SPI_MISO */
                                 4 1            /* ++MPP[ 4]: NF_IO[6] */
                                 5 1            /* ++MPP[ 5]: NF_IO[7] */
                                 6 1            /* ++MPP[ 6]: SYSRST_OUTn */
                                 7 2            /* MPP[ 7]: GPO[7] */
                                 8 1            /* ++MPP[ 8]: TW_SDA */
                                 9 1            /* ++MPP[ 9]: TW_SCK */
                                10 3            /* ++MPP[10]: UA0_TXD */
                                11 3            /* ++MPP[11]: UA0_RXD */
                                12 1            /* ++MPP[12]: SD_CLK */
                                13 1            /* ++MPP[13]: SD_CMD */
                                14 1            /* ++MPP[14]: SD_D[0] */
                                15 1            /* ++MPP[15]: SD_D[1] */
                                16 1            /* ++MPP[16]: SD_D[2] */
                                17 1            /* ++MPP[17]: SD_D[3] */
                                18 1            /* ++MPP[18]: NF_IO[0] */
                                19 1            /* ++MPP[19]: NF_IO[1] */
                                20 4            /* MPP[20]: GE1[ 0] */
                                21 4            /* MPP[21]: GE1[ 1] */
                                22 2            /* MPP[22]: GE1[ 2] */
                                23 2            /* MPP[23]: GE1[ 3] */
                                24 3            /* MPP[24]: GE1[ 4] */
                                25 3            /* MPP[25]: GE1[ 5] */
                                26 3            /* MPP[26]: GE1[ 6] */
                                27 3            /* MPP[27]: GE1[ 7] */
                                28 3            /* MPP[28]: GE1[ 8] */
                                29 3            /* MPP[29]: GE1[ 9] */
                                30 3            /* MPP[30]: GE1[10] */
                                31 3            /* MPP[31]: GE1[11] */
                                32 3            /* MPP[32]: GE1[12] */
                                33 3            /* MPP[33]: GE1[13] */
                                34 3            /* MPP[34]: GE1[14] */
                                35 3            /* MPP[35]: GE1[15] */
                                36 0            /* ++MPP[36]: GPIO[36] */
                                37 0            /* ++MPP[37]: GPIO[37] */
                                38 0            /* MPP[38]: GPIO[38] */
                                39 0            /* MPP[39]: GPIO[39] */
                                40 2            /* MPP[40]: TDM_SPI_SCK */
                                41 2            /* MPP[41]: TDM_SPI_MISO */
                                42 2            /* MPP[42]: TDM_SPI_MOSI */
                                43 0            /* ++MPP[43]: GPIO[43] */
                                44 0            /* ++MPP[44]: GPIO[44] */
                                45 0            /* ++MPP[45]: GPIO[45] */
                                46 0            /* ++MPP[46]: GPIO[46] */
                                47 0            /* ++MPP[47]: GPIO[47] */
                                48 0            /* ++MPP[48]: GPIO[48] */
                                49 0            /* ++MPP[49]: GPIO[49] */
                                >;
                };

                GPIO: gpio@10100 {
                        #gpio-cells = <3>;
                        compatible = "mrvl,gpio";
                        reg = <0x10100 0x20>;
                        gpio-controller;
                        interrupts = <35 36 37 38 39 40 41>;
                        interrupt-parent = <&PIC>;
                };

                rtc@10300 {
                        compatible = "mrvl,rtc";
                        reg = <0x10300 0x08>;
                };

                twsi@11000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        compatible = "mrvl,twsi";
                        reg = <0x11000 0x20>;
                        interrupts = <43>;
                        interrupt-parent = <&PIC>;
                };

                enet0: ethernet@72000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        model = "V2";
                        compatible = "mrvl,ge";
                        reg = <0x72000 0x2000>;
                        ranges = <0x0 0x72000 0x2000>;
                        local-mac-address = [ 00 00 00 00 00 00 ];
                        interrupts = <12 13 14 11 46>;
                        interrupt-parent = <&PIC>;
                        phy-handle = <&phy0>;

                        mdio@0 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "mrvl,mdio";

                                phy0: ethernet-phy@0 {
                                        reg = <0x8>;
                                };
                        };
                };

                serial0: serial@12000 {
                        compatible = "ns16550";
                        reg = <0x12000 0x20>;
                        reg-shift = <2>;
                        clock-frequency = <0>;
                        interrupts = <33>;
                        interrupt-parent = <&PIC>;
                };

                serial1: serial@12100 {
                        compatible = "ns16550";
                        reg = <0x12100 0x20>;
                        reg-shift = <2>;
                        clock-frequency = <0>;
                        interrupts = <34>;
                        interrupt-parent = <&PIC>;
                };

                usb@50000 {
                        compatible = "mrvl,usb-ehci", "usb-ehci";
                        reg = <0x50000 0x1000>;
                        interrupts = <48 19>;
                        interrupt-parent = <&PIC>;
                };

                xor@60000 {
                        compatible = "mrvl,xor";
                        reg = <0x60000 0x1000>;
                        interrupts = <5 6 7 8>;
                        interrupt-parent = <&PIC>;
                };

                sata@80000 {
                        compatible = "mrvl,sata";
                        reg = <0x80000 0x6000>;
                        interrupts = <21>;
                        interrupt-parent = <&PIC>;
                };
        };

        SRAM: sram@fd000000 {
                compatible = "mrvl,cesa-sram";
                reg = <0xfd000000 0x00100000>;
        };

        chosen {
                stdin = "serial0";
                stdout = "serial0";
        };
};

2.4) Сборка ядра.

i386# cd /usr/src11
i386# make -j4 buildkernel KERNCONF=STORA-NFS TARGET_ARCH=arm

Здесь все очевидно, параметр KERNCONF= задает файл с конфигом.
Убеждаемся, что сборка закончилась без ошибок.


3) TFTP-сервер и NFS-сервер уже есть в системе, DHCP-сервер нужно уставить:

i386# cd /usr/ports/net/isc-dhcp43-server
i386# make install clean

3.1) Настройка TFTP. В файле /etc/inetd.conf нужно раскомментировать строку:

tftp    dgram   udp     wait    root    /usr/libexec/tftpd      tftpd -l -s /tftpboot

И создать эту директорию:

i386# mkdir /tftpboot

3.2) Настройка NFS-сервера. Нужно создать директорию будущего корня и поместить строку в /etc/exports

i386# mkdir -p /nfsroot/stora11
i386# echo '/nfsroot -alldirs -maproot=0 -network 192.168.43/24' >> /etc/exports

3.3) Настройка DHCP-сервера. Конфиг в /usr/local/etc/dhcpd.conf приводим к такому виду:

authoritative;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;
option domain-name "localhost.net";
option domain-name-servers 192.168.43.1;

subnet 192.168.43.0 netmask 255.255.255.0 {
  range 192.168.43.70 192.168.43.96;
  option routers 192.168.43.1;
  option broadcast-address 192.168.43.255;
  option root-path "192.168.43.43:/nfsroot/stora11";
}

3.4) Правим стартовые скрипты и запускаем все демоны:

i386# echo 'inetd_enable="YES"' >> /etc/rc.conf
i386# echo 'nfs_server_enable="YES"' >> /etc/rc.conf
i386# echo 'mountd_enable="YES"' >> /etc/rc.conf
i386# echo 'mountd_flags="-r"' >> /etc/rc.conf
i386# echo 'rpc_statd_enable="YES"' >> /etc/rc.conf
i386# echo 'rpc_lockd_enable="YES"' >> /etc/rc.conf
i386# echo 'rpcbind_enable="YES"' >> /etc/rc.conf
i386# echo 'dhcpd_enable="YES"' >> /etc/rc.conf
i386# /etc/rc.d/inetd start
i386# /etc/rc.d/nfsd start
i386# /etc/rc.d/mountd start
i386# /etc/rc.d/rpcbind start
i386# /etc/rc.d/lockd start
i386# /etc/rc.d/statd start
i386# /usr/local/etc/rc.d/isc-dhcpd start

Убеждаемся, что все демоны запустились и не выдали никаких ошибок при запуске.


4) Копируем NFS-ядро в TFTP-директорию:

i386# cp /usr/obj/arm.arm/usr/src11/sys/STORA-NFS/kernel.bin /tftpboot/kernel_nfs.bin

Пробуем загрузить его. В консоли U-boot:

Marvell>> tftpboot 0x900000 kernel_nfs.bin

Должен быть вывод об успешной загрузке, примерно такой:

TFTP from server 192.168.43.43; our IP address is 192.168.43.10
Filename 'kernel_nfs.bin'.
Load address: 0x900000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ###############################################
done
Bytes transferred = 3900680 (3b8508 hex)

Если это не так, значит TFTP-сервер не работает или что-то не настроено.
Загружаем:

Marvell>> go 0x900000

Должны пробежать все устройства, определиться сетевой интерфейс, HDD (если вставлен) и в конце попытка примонтировать ФС через NFS:

## Starting application at 0x00900000 ...
Copyright (c) 1992-2015 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 11.0-CURRENT #2 r277964M: Fri Feb 13 01:42:41 MSK 2015
    root@nas2015n.localhost.ru:/usr/obj/arm.arm/usr/src11/sys/STORA-NAND arm
FreeBSD clang version 3.5.1 (tags/RELEASE_351/final 225668) 20150115
CPU: Feroceon 88FR131 rev 1 (Marvell core)
  Little-endian DC enabled IC enabled WA disabled DC streaming enabled
  BTB disabled L2 enabled L2 prefetch enabled
  WB enabled EABT branch prediction enabled
  16KB/32B 4-way instruction cache
  16KB/32B 4-way write-back-locking-C data cache
real memory  = 134213632 (127 MB)
avail memory = 125300736 (119 MB)
SOC: Marvell 88F6281 rev A1, TClock 200MHz
  Instruction cache prefetch enabled, data cache prefetch enabled
  256KB 4-way set-associative write-through unified L2 cache
random device not loaded; using insecure entropy
random: <Software, Yarrow> initialized
ofwbus0: <Open Firmware Device Tree>
simplebus0: <Flattened device tree simple bus> on ofwbus0
localbus0: <Marvell device bus> on ofwbus0
nand0: <Marvell NAND controller> mem 0xf9300000-0xf93fffff on localbus0
nandbus0: <NAND bus> on nand0
lnand0: <Samsung NAND 256MiB 3,3V 8-bit> on nandbus0
lnand0: Found BBT table for chip
ic0: <Marvell Integrated Interrupt Controller> mem 0x20200-0x2023b on simplebus0
timer0: <Marvell CPU Timer> mem 0x20300-0x2032f irq 1 on simplebus0
Event timer "CPUTimer0" frequency 200000000 Hz quality 1000
Timecounter "CPUTimer1" frequency 200000000 Hz quality 1000
gpio0: <Marvell Integrated GPIO Controller> mem 0x10100-0x1011f irq 35,36,37,38,39,40,41 on simplebus0
rtc0: <Marvell Integrated RTC> mem 0x10300-0x10307 on simplebus0
twsi0: <Marvell Integrated I2C Bus Controller> mem 0x11000-0x1101f irq 43 on simplebus0
iicbus0: <Philips I2C bus> on twsi0
iic0: <I2C generic I/O> on iicbus0
mge0: <Marvell Gigabit Ethernet controller> mem 0x72000-0x73fff irq 12,13,14,11,46 on simplebus0
mge0: Ethernet address: c4:3d:c7:4d:e7:61
miibus0: <MII bus> on mge0
e1000phy0: <Marvell 88E1116R Gigabit PHY> PHY 8 on miibus0
e1000phy0:  none, 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, 1000baseT, 1000baseT-master, 1000baseT-FDX, 1000baseT-FDX-master, auto
uart0: <16550 or compatible> mem 0x12000-0x1201f irq 33 on simplebus0
uart0: console (115740,n,8,1)
uart1: <16550 or compatible> mem 0x12100-0x1211f irq 34 on simplebus0
ehci0: <Marvell Integrated USB 2.0 controller> mem 0x50000-0x50fff irq 48,19 on simplebus0
usbus0: EHCI version 1.0
usbus0: set host controller mode
usbus0 on ehci0
mvs0: <Marvell 88F6281 SATA controller> mem 0x80000-0x85fff irq 21 on simplebus0
mvs0: Gen-IIe, 2 3Gbps ports, Port Multiplier supported with FBS
mvsch0: <Marvell SATA channel> at channel 0 on mvs0
mvsch1: <Marvell SATA channel> at channel 1 on mvs0
pcib0: <Marvell Integrated PCI/PCI-E Controller> mem 0xf1040000-0xf1041fff irq 44 on ofwbus0
pci0: <PCI bus> on pcib0
cryptosoft0: <software crypto>
Timecounters tick every 10.000 msec
usbus0: 480Mbps High Speed USB v2.0
ugen0.1: <Marvell> at usbus0
uhub0: <Marvell EHCI root HUB, class 9/0, rev 2.00/1.00, addr 1> on usbus0
ada0 at mvsch0 bus 0 scbus0 target 0 lun 0
ada0: <ST3000DM001-1CH166 CC43> ATA-8 SATA 3.x device
ada0: Serial Number Z1F0W87G
ada0: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada0: Command Queueing enabled
ada0: 2861588MB (5860533168 512 byte sectors: 16H 63S/T 16383C)
ada0: quirks=0x1<4K>
ada0: Previously was known as ad0
uhub0: 1 port with 1 removable, self powered

bootpc_init: wired to interface 'mge0'
Sending DHCP Discover packet from interface mge0 (c4:3d:c7:4d:e7:61)
mge0: link state changed to UP
Received DHCP Offer packet on mge0 from 0.0.0.0 (accepted)
Received DHCP Offer packet on mge0 from 0.0.0.0 (ignored)
Received DHCP Offer packet on mge0 from 0.0.0.0 (accepted)
Sending DHCP Request packet from interface mge0 (c4:3d:c7:4d:e7:61)
Received DHCP Ack packet on mge0 from 0.0.0.0 (accepted) (got root path)
mge0 at 192.168.43.70 server 0.0.0.0 boot file kernel_nfs.bin
subnet mask 255.255.255.0 router 192.168.43.1 rootfs 192.168.43.43:/nfsroot/stora11
Adjusted interface mge0
Trying to mount root from nfs: []...
Mounting from nfs:192.168.43.43/nfsroot/stora11 failed with error -1.
...
...
mountroot>

Этот вывод говорит о том, что система получила параметры через BOOTP и попыталась примонтировать корень через NFS, но не смогла, т.к. мы еще не подготовили NFS-root. Если загрузка ядра застревает на каком-то устройстве и не идет - что-то не так, возможно, ошибка в FDT-файле. Когда появилось mountroot> - можно переходить дальше.

4.1) Возвращаемся к собранному миру.

i386# cd /usr/src11

Указываем переменную куда установить мир - наш NFS-root (!!!Очень важно не ошибиться здесь и не пропустить параметр DESTDIR, иначе мир установится в текущую систему)

i386# setenv DESTDIR /nfsroot/stora11

Ставим мир:

i386# make installworld TARGET_ARCH=arm
i386# make distrib-dirs TARGET_ARCH=arm
i386# make distribution TARGET_ARCH=arm

Также ставим ядро и собранные модули:

i386# make installkernel KERNCONF=STORA-NFS TARGET_ARCH=arm

Проверяем, что мир стал куда надо:

i386# ls -l /nfsroot/stora11/

Правим начальные конфиги:

i386# touch $DESTDIR/etc/fstab
i386# touch $DESTDIR/etc/rc.conf   
i386# touch $DESTDIR/etc/resolv.conf   
i386# touch $DESTDIR/etc/motd
i386# echo 'hostname="stora-nfs.localhost.net"' >> $DESTDIR/etc/rc.conf
i386# echo 'ifconfig_mge0="inet 192.168.43.20 netmask 255.255.255.0"' >> $DESTDIR/etc/rc.conf
i386# echo 'defaultrouter="192.168.43.1"' >> $DESTDIR/etc/rc.conf
i386# echo 'rpcbind_enable="YES"' >> $DESTDIR/etc/rc.conf
i386# echo 'nfs_client_enable="YES"' >> $DESTDIR/etc/rc.conf
i386# echo 'rpc_lockd_enable="YES"' >> $DESTDIR/etc/rc.conf
i386# echo 'rpc_statd_enable="YES"' >> $DESTDIR/etc/rc.conf
i386# echo 'sshd_enable="YES"' >> $DESTDIR/etc/rc.conf
i386# echo 'sendmail_enable="NONE"' >> $DESTDIR/etc/rc.conf
i386# echo 'nameserver 192.168.43.1' >> $DESTDIR/etc/resolv.conf
i386# echo 'Welcome to FreeBSD/arm' > $DESTDIR/etc/motd
i386# echo 'PermitRootLogin yes' >> $DESTDIR/etc/ssh/sshd_config
i386# echo 'UseLogin yes' >> $DESTDIR/etc/ssh/sshd_config
i386# echo 'UseDNS no' >> $DESTDIR/etc/ssh/sshd_config

На этом можно ограничиться, остальное настроим уже непосредственно в загруженной системе.

4.2) Повторяем загрузку через TFTP:

Marvell>> tftpboot 0x900000 kernel_nfs.bin
Marvell>> go 0x900000

Если все сделано правильно, в результате мы увидим загруженную систему:

Trying to mount root from nfs: []...
NFS ROOT: 192.168.43.43:/nfsroot/stora11
Interface mge0 IP-Address 192.168.43.70 Broadcast 192.168.43.255
Setting hostuuid: 647b744a-bfde-11d3-9175-c43dc74de761.
Setting hostid: 0xae232d96.
Entropy harvesting: interrupts ethernet point_to_point swi.
Starting file system checks:
mount_nfs: can't update /var/db/mounttab for 192.168.43.43:/nfsroot/stora11
Mounting local file systems:.
Writing entropy file:.
Setting hostname: stora-nfs.localhost.net.
Starting Network: lo0.
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
        inet 127.0.0.1 netmask 0xff000000
Starting devd.
devd: cannot open pid file: Operation not supported
Starting pflogd:
ELF ldconfig path: /lib /usr/lib /usr/lib/compat /usr/local/lib
Creating and/or trimming log files.
Starting syslogd.
syslogd: cannot open pid file: Operation not supported
Starting rpcbind.
NFS access cache time=60
Clearing /tmp (X related).
Starting statd.
Starting lockd.
Updating motd:.
Mounting late file systems:.
Starting cron.
Starting background file system checks in 60 seconds.

Sat Jan  1 00:00:12 MSK 2000

FreeBSD/arm (stora-nfs.localhost.net) (ttyu0)

login:

4.3) Заходим под root и задаем пароль командой passwd, после чего уже можно будет заходить через SSH.
Установим таймзону и время.

stora# tzsetup

Нажать No, дальше выборать Europe -> Russian Federation -> MSK+XX

stora# ntpdate time.nist.gov

Т.к. в устройстве отсутствуют часы, нужно получать время каждый раз после загрузки. Добавим в автозагрузку:

stora# echo 'ntpdate_enable="YES"' >> /etc/rc.conf
stora# echo 'ntpdate_flags="-b time.nist.gov"' >> /etc/rc.conf

Дальше нужно установить swap, т.к. 128 Мб ОЗУ слишком мало и даже скомпилировать некоторые пакеты не получится - не хватит памяти. Swap разместим на первом разделе первого HDD, достаточно 256 Мб.
Внимание!!! Если у вас есть какие-то данные на HDD - они будут уничтожены, предполагается, что используется чистый HDD!
Делаем разметку через GPT:

stora# gpart destroy -F ada0
stora# gpart create -s gpt ada0
stora# gpart add -t freebsd-swap -l hdd0_swap -s 256M ada0

Устанавливаем swap и добавляем его в автомонтирование при загрузке:

stora# swapon /dev/gpt/hdd0_swap
stora# echo '/dev/gpt/hdd0_swap  none  swap  sw  0  0' >> /etc/fstab

Дальше можно устанавливать любой софт по вкусу. Удобнее всего это делать через систему портов:

stora# mkdir /usr/ports
stora# cd /usr/ports
stora# portsnap fetch
stora# portsnap extract

Установим, например, iperf:

stora# cd /usr/ports/benchmarks/iperf 
stora# make install clean

Надо запастись терпением - компиляция на ARM-платформе процесс очень медленный (это все ж не x86). Как вариант - можно настроить кросс-платформенную сборку портов на основной x86 системе, но этот способ нетривиальный и не учитывает зависимости, все необходимые библиотеки придется собирать вручную. В общем, этот способ описывать не буду.


5) Когда настройка системы закончена и все необходимое установлено - можно переносить систему на HDD.

5.1) Продолжим разметку HDD, сделаем еще 2 раздела - 4 Мб под ядро и 10 Гб (можно меньше) под систему, а оставшее место под хранилище:

stora# gpart add -t freebsd-ufs -l hdd0_kernel -s 4M ada0
stora# gpart add -t freebsd-ufs -l hdd0_root -s 10G ada0
stora# gpart add -t freebsd-ufs -l hdd0_data ada0

В результате у нас получилось 4 раздела: swap, ядро, система (4 Гб), данные:

stora# gpart show
=>        40  5860533088  ada0  GPT  (2.7T)
          40      524288     1  freebsd-swap  (256M)
      524328        8192     2  freebsd-ufs  (4.0M)
      532520     8388608     3  freebsd-ufs  (4.0G)
     8921128  5851611992     4  freebsd-zfs  (2.7T)
  5860533120           8        - free -  (4.0K)

Теперь нужно взять значения во 2-ом разделе (первый блок и кол-во блоков) и перевести в HEX.
Получим:
HEX(524328) = 0x80028
HEX(8192) = 0x2000
Это понадобится дальше для загрузки из U-boot.

5.2) Для переноса системы на HDD нужно пересобрать ядро с указанием системного раздела. Возвращаемся в x86 систему:

i386# cd /usr/src11
i386# cp /usr/src11/sys/arm/conf/STORA-NFS /usr/src11/sys/arm/conf/STORA-HDD

В конфиге STORA-HDD меняем и добавляем несколько строк:

ident           STORA-HDD

# раздел HDD, на котором будет корневая файловая система.
options         ROOTDEVNAME=\"ufs:/dev/ada0p3\"

Опции NFS и BOOTP можно убрать, они собираются в виде модулей.

Собираем новое ядро и копируем в рабочую NFS-директорию:

i386# make -j4 buildkernel KERNCONF=STORA-HDD TARGET_ARCH=arm
i386# cp /usr/obj/arm.arm/usr/src11/sys/STORA-HDD/kernel.bin /nfsroot/stora11/root/kernel_hdd.bin

Переходим в консоль Stora. записываем ядро:

stora# dd if=/root/kernel_hdd.bin of=/dev/gpt/hdd0_kernel bs=4k conv=sync

Теперь форматируем 3-ий раздел для системы, 4-й под данные и монтируем их:

stora# newfs -U /dev/gpt/hdd0_root
stora# newfs -U /dev/gpt/hdd0_data
stora# mkdir /hdd0_root
stora# mkdir /hdd0_data
stora# mount /dev/gpt/hdd0_root /hdd0_root
stora# mount /dev/gpt/hdd0_data /hdd0_data

Переносим все файлы:

stora# cd /
stora# pax -p eme -X -rw . /hdd0_root

Ставим точки монтирования в перенесенной системе:

stora# echo '/dev/gpt/hdd0_root  /  ufs  rw  0  0' >> /hdd0_root/etc/fstab
stora# echo '/dev/gpt/hdd0_data  /hdd0_data  ufs  rw  0  0' >> /hdd0_root/etc/fstab

Также можно выключить автозагрузку rpcbind, nfs, lockd, statd, и поправить другие конфиги, они уже будут в /hdd0_root/etc/

5.3) Перезагружаем Stora. В консоли U-boot надо остановить загрузку и ввести команды:

Marvell>> ide reset
Marvell>> ide read 0x900000 0x80028 0x2000
Marvell>> go 0x900000

Если FreeBSD загрузилась и все в порядке - можно записать эти команды для автозагрузки в U-boot:

Marvell>> set fbsdhddboot 'ide reset; ide read 0x900000 0x80028 0x2000; go 0x900000'
Marvell>> set bootcmd 'run fbsdhddboot'
Marvell>> saveenv
Marvell>> reset

Все. Теперь Stora загружается самостоятельно с установленной FreeBSD, можно отключать консольный кабель и запускать хранилку в бой.

----------------------------------

Дополнительные возможности.
Нижеописанные возможности работают частично или работают плохо, но я решил их тоже добавить к статье, может кому-то будет полезно.

6) FreeBSD можно полностью прошить во внутренний NAND Flash, только swap будет на HDD. Плюсы очевидны: даже при замене или сбое HDD, система всегда будет в работоспособном состоянии (без swap система тоже будет работать). Но есть и нюансы: размер NAND Flash всего 256 Мб, поэтому систему придется максимально урезать и убрать все лишнее, после чего сборка и доустановка софта будет уже невозможна - нужно заранее все протестировать, собрать рабочий вариант и записать на флеш. Этот вариант подходит тем, кому нужна необслуживаемая хранилка в режиме "один раз настроил и забыл". Если вы любите постоянно что-то устанавливать или обновлять софт - лучше развернуть систему на HDD.
Ну и очевидно, что придется затереть заводскую прошивку от Netgear.

Но самый существенный минус заключается в том, что NANDFS все еще находится в стадии "highly experimental feature", и в течении времени работающая система начинает съедать свободное место NAND Flash, притом что никакие файлы не пишутся. Информации по NANDFS крайне мало и мне так и не удалось победить этот глюк.

6.1) Подготовка для переноса в NAND Flash начинается с разметки. Это делается в конфиге Flattened Device Tree. Если вернутся в начало и посмотреть файл stora.dts - там будет такой блок:

                nand@0,0 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "mrvl,nfc";
                        reg = <0x0 0x0 0x00100000>;
                        bank-width = <2>;
                        device-width = <1>;

                        slice@0 {
                                reg = <0x0 0x100000>;
                                label = "uboot";
                                read-only;
                        };

                        slice@100000 {
                                reg = <0x100000 0x400000>;  
                                label = "kernel";
                        };

                        slice@500000 {
                                reg = <0x500000 0xfa00000>;
                                label = "root";
                        };          
                };

Здесь видно, что заданы 3 раздела (slice). Первый раздел размером 0x100000 (1 Мбайт) - это U-boot, его трогать нельзя и поэтому там стоит флаг read-only. Все, что после 0x100000 можно смело использовать, а это около 254 Мбайт. Второй раздел размером 4 Мбайта - ядро. Третий раздел около 250 Мбайт - под систему. Логика разметки аналогична GPT HDD - каждый слайс определен как "начало" - "размер" в байтах, только в HEX. Сооответственно, начало следующего слайса будет равно "начало предыдущего" + "размер предыдущего". Таким образом, если нужно посчитать слайс на 250 Мбайт - это будет HEX(250*1024*1024) = fa00000. Размер блока NAND Flash - 1024 байта, поэтому размеры слайсов должны быть кратны 1024.

Как и в случае с HDD, ядро нужно тоже пересобрать для статической загрузки с раздела NAND Flash.

i386# cd /usr/src11
i386# cp /usr/src11/sys/arm/conf/STORA-HDD /usr/src11/sys/arm/conf/STORA-NAND

В конфиге STORA-NAND добавляем и меняем строки:

ident            STORA-NAND

options        NANDFS
options          ROOTDEVNAME=\"nandfs:/dev/gnand0s.root\"

и собираем:

i386# make -j4 buildkernel KERNCONF=STORA-NAND TARGET_ARCH=arm
i386# cp /usr/obj/arm.arm/usr/src11/sys/STORA-NAND/kernel.bin /nfsroot/stora11/root/kernel_nand.bin

6.2) Чтобы вместить систему и необходимые пакеты на 250 Мбайт флеша, нужна пересборка мира. Мы уберем различные средства компиляции, библиотеки, man'ы и много чего еще. Мой вариант файла /etc/src.conf представлен ниже. Но нужно отметить, что это очень минималистичная сборка и подходит только для вариантов сразу все настроить, запустить и забыть. В зависимости от используемого софта, некоторые библиотеки могут отсутсвовать и их придется скопировать вручную из ранее собранного мира.
/etc/src.conf:

WITH_NAND=YES
WITHOUT_ACCT=YES
WITHOUT_ACPI=YES
WITHOUT_AMD=YES
WITHOUT_APM=YES
WITHOUT_ASSERT_DEBUG=YES
WITHOUT_ATM=YES
WITHOUT_AUDIT=YES
WITHOUT_AUTHPF=YES
WITHOUT_AUTOFS=YES
WITHOUT_BHYVE=YES
WITHOUT_BINUTILS=YES
WITHOUT_BINUTILS_BOOTSTRAP=YES
WITHOUT_BLUETOOTH=YES
WITHOUT_BMAKE=YES
WITHOUT_BOOT=YES
WITHOUT_BZIP2=YES
WITHOUT_BZIP2_SUPPORT=YES
WITHOUT_CALENDAR=YES
WITHOUT_CAPSICUM=YES
WITHOUT_CASPER=YES
WITHOUT_CDDL=YES
WITHOUT_CCD=YES
WITHOUT_CTF=YES
WITHOUT_ZFS=YES
WITHOUT_CLANG=YES
WITHOUT_CLANG_EXTRAS=YES
WITHOUT_CLANG_FULL=YES
WITHOUT_CPP=YES
WITHOUT_CROSS_COMPILER=YES
WITHOUT_CTM=YES
WITHOUT_CUSE=YES
WITHOUT_CXX=YES
WITHOUT_DICT=YES
WITHOUT_DMAGENT=YES
WITHOUT_DOCCOMPRESS=YES
WITHOUT_ED_CRYPTO=YES
WITHOUT_EXAMPLES=YES
WITHOUT_FLOPPY=YES
WITHOUT_FMTREE=YES
WITHOUT_FORMAT_EXTENSIONS=YES
WITHOUT_FORTH=YES
WITHOUT_FP_LIBC=YES
WITHOUT_FREEBSD_UPDATE=YES
WITHOUT_GAMES=YES
WITHOUT_GCC=YES
WITHOUT_GCOV=YES
WITHOUT_GDB=YES
WITHOUT_GNU=YES
WITHOUT_GNU_SUPPORT=YES
WITHOUT_GNUCXX=YES
WITHOUT_GPIB=YES
WITHOUT_GROFF=YES
WITHOUT_GSSAPI=YES
WITHOUT_HAST=YES
WITHOUT_HTML=YES
WITHOUT_HYPERV=YES
WITHOUT_ICONV=YES
WITHOUT_INET6=YES
WITHOUT_INET6_SUPPORT=YES
WITHOUT_INFO=YES
WITHOUT_INSTALLLIB=YES
WITHOUT_IPFILTER=YES
WITHOUT_IPFW=YES
WITHOUT_IPX=YES
WITHOUT_IPX_SUPPORT=YES
WITHOUT_JAIL=YES
WITHOUT_KDUMP=YES
WITHOUT_KERBEROS=YES
WITHOUT_KERBEROS_SUPPORT=YES
WITHOUT_KERNEL_SYMBOLS=YES
WITHOUT_KVM=YES
WITHOUT_KVM_SUPPORT=YES
WITHOUT_LEGACY_CONSOLE=YES
WITHOUT_LIB32=YES
WITHOUT_LIBCPLUSPLUS=YES
WITHOUT_LIBPTHREAD=YES
WITHOUT_LPR=YES
WITHOUT_LS_COLORS=YES
WITHOUT_MAIL=YES
WITHOUT_MAILWRAPPER=YES
WITHOUT_SENDMAIL=YES
WITHOUT_MAN=YES
WITHOUT_MANCOMPRESS=YES
WITHOUT_MAN_UTILS=YES
WITHOUT_NDIS=YES
WITHOUT_NCURSESW=YES
WITHOUT_NETGRAPH=YES
WITHOUT_NETGRAPH_SUPPORT=YES
WITHOUT_NS_CACHING=YES
WITHOUT_OFED=YES
WITHOUT_PC_SYSINSTALL=YES
WITHOUT_PF=YES
WITHOUT_PMC=YES
WITHOUT_PORTSNAP=YES
WITHOUT_PPP=YES
WITHOUT_QUOTAS=YES
WITHOUT_RCS=YES
WITHOUT_RESCUE=YES
WITHOUT_ROUTED=YES
WITHOUT_SHAREDOCS=YES
WITHOUT_SOURCELESS=YES
WITHOUT_SOURCELESS_HOST=YES
WITHOUT_SOURCELESS_UCODE=YES
WITHOUT_SSP=YES
WITHOUT_SVNLITE=YES
WITHOUT_SYMVER=YES
WITHOUT_SYSINSTALL=YES
WITHOUT_TALK=YES
WITHOUT_TESTS=YES
WITHOUT_TESTS_SUPPORT=YES
WITHOUT_TOOLCHAIN=YES
WITHOUT_UNBOUND=YES
WITHOUT_WIRELESS=YES
WITHOUT_WIRELESS_SUPPORT=YES
WITHOUT_WPA_SUPPLICANT_EAPOL=YES

Ставим новый мир и модули ядра:

i386# cd /usr/src11
i386# mkdir -p /nfsroot/stora11-nand
i386# setenv DESTDIR /nfsroot/stora11-nand
i386# make installworld TARGET_ARCH=arm
i386# make distrib-dirs TARGET_ARCH=arm
i386# make distribution TARGET_ARCH=arm
i386# make installkernel KERNCONF=STORA-NAND TARGET_ARCH=arm

Повторяем начальную конфигурацию из п. 4.1.
Таким образом, размер системы получается около 70 Мбайт. Неплохо, но еще нужно установить доп. софт, многие пакеты довольно объемные.

6.3) Подготовка пакетов.
Т.к. все средства компиляции уже убраны, сборка софта из системы портов будет невозможна - нужно заранее подготовить все пакеты.
Загрузим подготовленную систему через NFS cоздадим директорию для пакетов:

stora# mkdir /root/packages
stora# cd /root/packages

Делаем такой скрипт create_all_packages.sh:

#!/bin/sh

for pkgname in `pkg info | cut -f 1 -d " "` ; do
       pkg create $pkgname
done

и запускаем его:

stora# ./create_all_packages.sh

Все установленные пакеты будут созданы в этой директории.

6.4) Загружаем новый мир через NFS. В конфиге dhcpd.conf нужно поправить root-path:

....
  option root-path "192.168.43.43:/nfsroot/stora11-nand";
....
i386# /usr/local/etc/rc.d/isc-dhcpd restart
Marvell>> tftpboot 0x900000 kernel_nfs.bin
Marvell>> go 0x900000

Монтируем старый мир, где лежат подготовленные пакеты:

stora# mount_nfs 192.168.43.43:/nfsroot/stora11 /mnt
stora# cd /mnt/root/packages

Далеко не все зависимости требуются для запуска приложения, поэтому можно ставить пакеты без учета зависимостей, добавлять по одному:

stora# pkg add -M minicom-2.7.txz

Также многие пакеты ставят очень много лишних приложений и библиотек, которые тоже можно удалить.

6.5) Когда все готово, можно переносить систему на Flash.
Разделы флеш-памяти уже видны в системе:

stora# ls /dev/ | grep gnand0
gnand0
gnand0s.kernel
gnand0s.root
gnand0s.uboot

Прошиваем ядро:

stora# nandtool erase dev=/dev/gnand0s.kernel
stora# dd if=/mnt/root/kernel_nand.bin of=/dev/gnand0s.kernel bs=2k conv=sync
...
3180544 bytes transferred in 3.897240 secs (816102 bytes/sec)

Записываем точный размер ядра в байтах и переводим в HEX, это понадобится для загрузки в U-boot
HEX(3180544)=0x308800

Форматируем раздел под систему:

stora# nandtool erase dev=/dev/gnand0s.root
stora# newfs_nandfs /dev/gnand0s.root
....
filesystem created succesfully
total segments: 0x7ca valid segments: 0x7c5
total space: 249 MB free: 248 MB

В процессе могут быть сообщения о bad-блоках - ничего страшного, в NAND они всегда есть.

stora# mkdir /nand
stora# mount -t nandfs /dev/gnand0s.root /nand

Переносим все файлы таким способом - делаем архив, потом его распаковываем (особенность NANDFS):

i386# cd /nfsroot
i386# tar -cf /nfsroot/stora11/root/nand.tar stora11-nand/
stora# tar -xf /mnt/root/nand.tar -C /nand --strip-components=1

Проверяем, что все скопировалось, правим начальные конфиги (можно убрать NFS) и т.д.

stora# unount /nand
stora# shutdown -r now

6.6) Останавливаем U-boot и загружаемся с NAND Flash:

Marvell>> nand read 0x900000 0x100000 0x308800
Marvell>> go 0x900000

Система должна загрузиться. Если так, то пропишем в автозагрузку:

Marvell>> setenv fbsdnandboot 'nand read 0x900000 0x100000 0x308800; go 0x900000'
Marvell>> setenv bootcmd 'run fbsdnandboot'
Marvell>> saveenv
Marvell>> reset

Готово!

7) Аппаратное шифрование
В Marvell Kirkwood есть аппаратный криптографический ускоритель, который поддерживается драйвером cesa. К сожалению, включение аппаратного ускорения приводило к многочисленным ошибкам и частым kernel panic, поэтому я убрал его из конфига ядра и FDT-файла. Стабильной работы не было ни на одной версии FreeBSD (9.3, 10.1, 11-CURRENT). А так, в тестах openssl speed производительность увеличивается на порядки и сравнима с x86-системами без ускорителя:

# openssl speed -evp aes-128-cbc -engine cryptodev
aes-128-cbc      10247.68k    10950.52k    58538.54k   585891.84k  2756706.30k
aes-128-cbc       5174.53k    25042.94k    58371.72k   233753.80k  2054946.82k
aes-128-cbc       5702.80k    27622.06k    53523.80k   212348.56k  8206155.78k
# openssl speed -evp aes-256-cbc -engine cryptodev
aes-256-cbc       5124.61k    11706.37k   128188.42k   287784.96k  1551682.76k
aes-256-cbc       4556.80k    23423.27k    91497.62k   460560.79k  7838105.60k

В программном режиме:

aes-128-cbc       7917.35k    10135.18k    10857.05k    11037.59k    11075.96k
aes-256-cbc       6371.93k     7771.82k     8200.81k     8290.30k     8327.77k

Если же кто-то хочет побаловаться, то в конфиг ядра нужно добавить строки:

device cesa
device    crypto
device  cryptodev

а в файл stora.dts добавить описание устройства в блок  SOC: soc88f6281@f1000000

                crypto@30000 {
                        compatible = "mrvl,cesa";
                        reg = <0x30000 0x10000>;
                        interrupts = <22>;
                        interrupt-parent = <&PIC>;

                        sram-handle = <&SRAM>;
                };

Задействовать криптографический ускоритель можно везде, где используется библиотека OpenSSL: шифрование дисков через GEOM_ELI, OpenSSH, SFTP, IPSEC, OpenVPN и т.д. Аппаратно поддерживаются следующие алгоритмы: RSA, DSA, DH, DES-CBC, DES-EDE3-CBC, AES-128-CBC, AES-192-CBC, AES-256-CBC.


8) Шифрование дисков.
Шифрование дисков делается с помощью класса GEOM_ELI. Но из-за глючности аппаратного ускорения эта функция почти бесполезна - в программном режиме скорость чтения/записи на диск ну очень слабая (порядка 3-4 Мбайт/с, с аппаратным ускорением до 15-20 Мбайт/с). Тем не менее, такая возможность есть и оно работает. В текущей конфигурации ядра класс GEOM_ELI собирается в виде модуля и его можно подгрузить при необходимости командой

stora# kldload geom_eli.ko

Если нужна постоянная поддержка, нужно пересобрать ядро с опциями

options   GEOM_ELI
device     crypto

Как делается шифрование - читаем man geli.


9) Поддержка ZFS
Общие впечатления от ZFS на этом девайсе такие: работает, но очень со скрипом. Серьезных ошибок и kernel panic ни разу не поймал, но система нагружается очень сильно, может зависнуть - 128 Мб действительно катастрофически мало для ZFS. Кроме того, сделать какой-либо тюнинг параметров ядра также невозможно, поскольку мы загружаем бинарное ядро сразу из U-boot, конфиг /boot/loader.conf игнорируется. Так что использовать ZFS на боевой хранилке я бы все же не рекомендовал.
Скорости примерно такие: zpool scrub делается со скоростью 80-85 Мбайт/с, что весьма неплохо, но сама система на время скрабирования вгоняется в жесточайший ступор, реагирует но консоль с огромными тормозами. 

Для поддержки ZFS нужно пересобрать мир, т.к. всю поддержку ZFS мы отключили в /etc/src.conf. Несколько строчек нужно заменить с WITHOUT на WITH:

WITH_CDDL=YES
WITH_CTF=YES
WITH_ZFS=YES

И пересобрать мир.

Ядро также нужно пересобрать - при сборке ядра для ARM, модули необходимые для работы ZFS по умолчанию не собираются, даже если в src.conf указано WITH_ZFS=YES. Возможно, разработчики считают, что код ZFS еще недостаточно адаптирован для ARM. Но тем не менее, модули можно собрать и ZFS работает. Для сборки нужно немного поправить файл /usr/src11/sys/cddl/compat/opensolaris/sys/cpuvar.h:

Index: sys/cddl/compat/opensolaris/sys/cpuvar.h
===================================================================
--- sys/cddl/compat/opensolaris/sys/cpuvar.h    (revision 227813)
+++ sys/cddl/compat/opensolaris/sys/cpuvar.h    (working copy)
@@ -50,6 +50,9 @@

  /* Some code may choose to redefine this if pcpu_t would be more useful. */
  #define cpu_t  solaris_cpu_t
+#ifdef cpu_id
+#undef cpu_id
+#endif
  #define        cpu_id  cpuid

  extern solaris_cpu_t    solaris_cpu[];

Затем, в конфиг ядра нужно добавить необходимые модули в список MODULES_OVERRIDE: zfs opensolaris acl_nfs4 zlib krpc.
И пересобрать ядро, установить новые модули.

i386# make -j4 buildkernel KERNCONF=STORA-NFS TARGET_ARCH=arm
i386# make installkernel KERNCONF=STORA-NFS TARGET_ARCH=arm

ZFS-пул можно сделать только под хранилище. Перенести саму систему на ZFS не получится, т.к. штатный U-boot не поддерживает загрузку ubldr с ZFS, а в случае бинарного ядра попытка примонтировать root-раздел происходит раньше, чем инициализируется ZFS-модуль. В общем, разметка первых 3-х разделов на диске остается прежней - система будет загружаться с UFS или NAND, как описано в разделах 5 и 6. А вот 4-ый раздел переделаем под ZFS:

stora# gpart delete -i 4 ada0
stora# gpart add -t freebsd-zfs -l hdd0_data ada0

В итоге получается такая разметка:

stora# gpart show
=>        40  5860533088  ada0  GPT  (2.7T)
          40      524288     1  freebsd-swap  (256M)
      524328        8192     2  freebsd-ufs  (4.0M)
      532520     8388608     3  freebsd-ufs  (4.0G)
     8921128  5851611992     4  freebsd-zfs  (2.7T)
  5860533120           8        - free -  (4.0K)

Загружаем модуль ZFS:

stora# kldload zfs.ko

Попутно загрузятся еще несколько модулей, и появится сообщение:

ZFS WARNING: Recommended minimum RAM size is 512MB; expect unstable behavior.
ZFS WARNING: Recommended minimum kmem_size is 512MB; expect unstable behavior.
             Consider tuning vm.kmem_size and vm.kmem_size_max
             in /boot/loader.conf.
ZFS filesystem version: 5
ZFS storage pool version: features support (5000)

Якобы, нужно минимум 512 Мб ОЗУ...
Последняя строка отображает максимальную версию ZFS-пула - 5000 - собственная версия ZFS в FreeBSD начиная с 10.0, несовместимая с другими реализациями ZFS. Для кросс-совместимости с Solaris, FUSE и т.д. нужно создавать пул с меньшей версией, например 28. Повысить версию пула можно, т.е. можно мигрировать с версии 28 на 5000, понизить - нельзя. Впрочем, все аспекты работы с ZFS выходят далеко за рамки этого мануала, поэтому ограничимся только самыми базовыми функциями.

Создание пула:

stora# zpool create media gpt/hdd0_data

Пул смонтируется в /media

Выключаем все по максимуму:

stora# zfs set checksum=off media
stora# zfs set compression=off media
stora# zfs set atime=off media

Добавляем в автозагрузку:

stora# echo 'zfs_enable="YES"' >> /etc/rc.conf

Думаю, на хранилках с 512 Мб ОЗУ все будет хорошо с ZFS, но у меня такой нет, а покупать ради экспериментов не хочется.

2

Re: Установка FreeBSD на Netgear Stora с поддержкой ZFS

Спасибо, отличное руководство.

Столкнулся с тем что если мир (для версии 10) собран с WITHOUT_SSP=YES то потом в сторе ничего не собирается.
не хватает библиотек libssp*

После пересборки на хост машине и копировании библиотек на стору, вроде все заработало.