[Из песочницы] Обновление Linux в устройстве на базе чипа Altera SoC FPGA и получение доступа с этого устройства к расшаренным сетевым ресурсам Windows-сервера

878c5b06c4b14fe88135f09a53de8a35.jpg

Недавно компания Terasic начала продажи весьма интересной платы DE0-Nano-SoC Kit. Интересна она тем, что за весьма скромную цену предлагается очень мощный и функционально-насыщенный комплект разработчика на основе чипа Altera Cyclone V SoC FPGA со встроенным двухъядерным процессором ARM Cortex-A9. Кроме того, производитель в комплекте с платой даёт ОС Linux, развёрнутую на карту памяти MicroSD.

Но получив эту плату в своё распоряжение, я довольно быстро наткнулся на несколько проблем, обусловленых тем, что Linux был скомпилирован из исходников Yocto Project. В основном все проблемы были связаны с отсутствием общедоступных репозиториев, из которых можно было бы добавить в систему недостающие компоненты. Например, для того, чтобы получить доступ с этого устройства через сеть к расшаренным ресурсам Windows-сервера, в ядре не хватало модуля поддержки файловой системы Cifs.

Поэтому прежде всего было решено обновить ядро, заменить Yocto на более привычный Debian Wheezy и доустановить всё, что необходимо для доступа к расшаренным ресурсам Windows-сервера.
Процесс сборки изучался мной и выполнялся следуя рекомендациям из этой статьи, за что её автору Des333 огромное спасибо!

Полная переделка в мои планы не входила, поэтому загрузчики на карточке было решено оставить родные — от образа Linux 3.13, идущего в комплекте с платой. Так что раздел с типом A2 было решено не трогать совсем.

Задачи


  • Обновить ядро Linux
  • Заменить RootFS на Debian 7
  • Доточить образ так, чтобы его можно было апдейтить из Интернета
  • Примонтировать директорию, расшаренную на сервере Windows


Сборка ядра


Так как основной моей рабочей средой по жизни является Windows, то все действия по сборке Linux выполнялись из-под ОС Linux Mint 17.2 Cinnamon, установленной на виртуальную машину.

1. Запускаем терминалку и входим в root-режим — чтобы не набирать каждый раз команду sudo:

sudo -i


При этом /root будет нашей домашней директорией — всё будем делать в ней.

2. Компилировать ядро будем с помощью кросс-компилятора, входящего в пакет Altera SoC Embedded Design Suite (EDS). Поэтому скачиваем и устанавливаем самый свежий пакет Altera SoC EDS. На данный момент времени Altera SoC EDS имеет версию 15.0. Скачать этот пакет можно прямо с сайта Альтеры.

Altera SoC EDS установится в директорию /root/altera/15.0.

3. Устанавливаем build-essential:

apt-get install build-essential


4. Установливаем libncurses:

apt-get install libncurses5-dev


5. Скачиваем исходники linux-socfpga из репозиториев Альтеры и распаковываем их в домашнюю директорию:

  • Заходим в релизы linux-socfpga в репозиториях Альтеры
  • Находим нужный релиз. Я выбрал версию 4.1 — так как это была самая свежая стабильная версия на данный момент времени
  • Скачиваем архив с исходниками
  • Распаковываем исходники в домашнюю директорию


В результате появляется директория /root/linux-socfpga-4.1 с исходниками ядра Linux версии 4.1.

6. Запускаем альтеровский скрипт, который запустит новый BASH и подправит в нём некоторые переменные окружения (например, PATH). Все действия по компиляции будем проводить не выходя из этого BASH:

cd /root/altera/15.0/embedded
./embedded_command_shell.sh


7. Создаём несколько переменных окружения:

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export LOADADDR=0x8000


8. Создаём дефолтную конфигурацию для socfpga:

cd /root/linux-socfpga-4.1
make socfpga_defconfig


При этом будет создан конфигурационный файл .config, заточенный для компиляции под ARM.

9. Добавляем недостающие компоненты в конфигурацию ядра (или удаляем лишние):

make menuconfig


При этом откроется псевдографическое окно с менюшками.
29d96c1546944733bc8b48540dc32cc8.gif


Нам нужно добавить драйвер файловой системы CIFS — чтобы иметь возможность заходить на сетевые расшаренные ресурсы. Для этого идём по пути File Systems → Network File Systems, становимся на CIFS Support и нажимаем клавишу пробел — напротив строки CIFS Suport должна появиться буква M — значит это драйвер, не встраиваемый в ядро. Нужно будет позднее скомпилировать его отдельно и положить в директорию внешних модулей.

Также нужно включить поддержку HighMem — иначе система не сможет использовать верхние 256 мегабайт ОЗУ. Для этого идём по пути Kernel Features → High Memory Support и также нажимаем клавишу пробел.

Выходим из меню — нажимаем EXIT пока не выйдем. На вопрос — надо ли сохранять конфигурацию — отвечаем Yes.

10. Компилируем ядро:

make uImage


В моём случае виртуальной машине было отдано только одно ядро. Процесс компиляции занял около 20 минут. Если же компилирование будет выполняться в машине с несколькими ядрами, то для скорости можно распараллелить процесс компиляции на несколько ядер. Для этого надо явно задать количество ядер через опцию -j:

make -j 3 uImage


11. Компилируем dtb-файл, соответствующий нашему устройству. Если воспользоваться старым dtb-файлом, то или устройство повиснет при загрузке или будут страшные глюки при работе:
В результате компиляции создалось два файла:

/root/linux-socfpga-4.1/arch/arm/boot/zImage
/root/linux-socfpga-4.1/arch/arm/boot/dts/socfpga_cyclone5_sockit.dtb


12. Компилируем модуль CIFS:

make M=fs/cifs


13. Компилируем все модули криптографии — они понадобятся при монтировании расшаренных ресурсов Windows:

make M=crypto


14. Копируем файлы ядра и dtb на карточку. Исходно карточка была нарезана так, что ядро и DTB-файл лежали на отдельном партишене FAT32. Вот на него эти файлы и записываем. Единственное замечание: DTB-файл нужно переименовать — чтобы он назывался также, как тот, который уже лежит на разделе FAT32 карточки:

  • Подключаем карточку к виртуальной машине. Мне пришлось воспользоваться внешним кардридером, подключенным прямо к порту USB2 компьютера. Сделать то-же самое через встроенный в компьютер кардридер почему-то не удалось. Также не удалось подсоединить внешний кардридер к виртуальной машине, если подключать его через порт USB3.
  • Произойдёт автомонтирование разделов карточки — нельзя размонтировать разделы через GUI, потому что в этом случае происходит полное отключение кардридера от виртуальной машины.
  • Смотрим названия примонтированных разделов:
    mount
    
    

    Увидим нечто в этом роде:
    /dev/sdb1 on /media/user/F725-1429 type vfat (rw,nosuid,nodev,uid=1000,gid=1000,shortname=mixed,dmask=0077,utf8=1,showexec,flush,uhelper=udisks2)
    /dev/sdb2 on /media/user/41cad05c-898e-49a3-9d00-02b92fa817ba type ext3 (rw,nosuid,nodev,uhelper=udisks2)
    
    

    Раздел типа vfat (первая строка) — то, что нас интересует в данный момент.
  • Смотрим, что лежит на разделе vfat:
    ll /media/user/F725-1429
    
    

    Видим нечто в этом роде:
    -rw-r--r--  1 user user 1164128 Apr 20 20:23 de0_nano_soc.rbf
    -rw-r--r--  1 user user   15274 Jul 26 17:08 socfpga.dtb
    -rw-r--r--  1 user user     176 Apr 20 19:59 u-boot.scr
    -rw-r--r--  1 user user 3371472 Jul 29 16:50 zImage
    
    

    Значит dtb-файл называется socfpga.dtb.
  • Копируем наши файлы на карточку:
    cp /root/linux-socfpga-4.1/arch/arm/boot/zImage /media/user/F725-1429/
    cp /root/linux-socfpga-4.1/arch/arm/boot/dts/socfpga_cyclone5_sockit.dtb /media/user/F725-1429/socfpga.dtb
    
    


Сборка файловой системы


Этот подраздел во многом повторяет то, что написано в этой статье, но тем не менее я привожу его полностью, чтобы в дальнейшем было проще пользоваться этим руководством.

Собирать будем Debian 7 Wheezy:

1. Устанавливаем пакеты, которые понадобятся для сборки файловой системы:

apt-get install debootstrap qemu-user-static binfmt-support


2. Создаем директорию и загружаем в неё все необходимые файлы:

cd /root
mkdir debian7
debootstrap --arch armel --foreign wheezy debian7 http://ftp.debian.org/debian


3. Чтобы запускать приложения, собранные под ARM-архитектуру, будем использовать qemu static. Для этого скопируем файл в нашу директорию debian7:

cp /usr/bin/qemu-arm-static debian7/usr/bin/


4. Переходим в нашу новую файловую систему:

chroot debian7 /bin/bash


5. Если приглашение интерпретатора изменилось на «I have no name!@hostname:/#», значит всё прошло успешно.
Заканчиваем процесс сборки:

/debootstrap/debootstrap --second-stage


6. В /etc/inittab оставляем следующие строки:

/etc/inittab
id:5:initdefault:
si::sysinit:/etc/init.d/rcS
~~:S:wait:/sbin/sulogin
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
z6:6:respawn:/sbin/sulogin
S:2345:respawn:/sbin/getty 115200 console


7. Устанавливаем пароль для root-аккаунта:

passwd


8. Запаковываем новую файловую систему в архив:

tar -cpzf debian7.tar.gz --exclude=debian7.tar.gz  /


9. Выходим из chroot:

exit


10. Размонтируем и затем форматируем раздел ext3 на карточке (названия разделов смотрим в пункте 14 из сборки ядра):

umount /dev/sdb2
mkfs.ext3 /dev/sdb2


11. Монтируем раздел ext3:

mount /dev/sdb2 /mnt/


12. Распаковываем архив с файловой системой на карточку в раздел ext3:

tar -xzf /root/debian7/debian7.tar.gz -C /mnt/


13. Так как мы хотим подключаться к расшаренным ресурсам на сервере Windows, то необходимо записать на карточку внешние модули, скомпилированные на этапах 12 и 13 процесса сборки ядра:

cd /mnt/lib
mkdir modules
mkdir modules/4.1.0
mkdir modules/4.1.0/extra
mkdir modules/4.1.0/kernel
mkdir modules/4.1.0/kernel/crypto
cp /root/linux-socfpga-4.1/fs/cifs/cifs.ko ./modules/4.1.0/extra/
cp /root/linux-socfpga-4.1/crypto/*.ko ./modules/4.1.0/kernel/crypto/


14. Размонтируем разделы:

umount /dev/sdb1
umount /dev/sdb2


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

Окончательная доводка


После загрузки устройства дотачиваем образ на месте:

1. Логинимся в Debian на устройстве, подключившись к нему через встроенный serial-порт.

2. Генерим файлы с информацией о внешних модулях ядра:

depmod -a


3. Добавляем в список репозиториев репозиторий Debian 7 (я добавил немецкий сервер):

echo "deb http://ftp.de.debian.org/debian wheezy main" > /etc/apt/sources.list


4. Подключаем устройство к Ethernet-сети. Получаем адрес по DHCP:

dhclient -4 eth0


5. Поднимаем NTP, так как с неправильным временем не удастся примонтировать расшаренные ресурсы:

apt-get update
apt-get install ntp


6. Устанавливаем наш часовой пояс:

dpkg-reconfigure tzdata


7. Для проверки, что всё собралось нормально, монтируем серверную шару. Например, в моём случае я делал это так:

mount //192.168.48.4/distrib /mnt -o username=jok40


8. Устанавливаем SSH-сервер. Пользоваться serial-пором неудобно, так как при работе через него происходит заворот набираемых команд на начало строки после достижения колонки 80:

apt-get install openssh


9. Назначаем статический адрес интерфейсу eth0 — чтобы в дальнейшем проще было подключаться к устройству по SSH. Для этого редактируем файл interfaces:

nano /etc/network/interfaces


В моём случае он стал выглядеть вот так:

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet static
address   192.168.48.27
netmask   255.255.255.0
gateway   192.168.48.1
network   192.168.48.0
broadcast 192.168.48.255

auto eth0


10. Редактируем файл resolv.conf — чтобы нормально работал DNS-клиент:

nano /etc/resolv.conf


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

nameserver 192.168.48.1
nameserver 8.8.8.8


11. Перезагружаем устройство.

12. Для проверки, что всё сделано правильно

подключаемся к устройству по SSH через Ethernet:
4ab31accf58b4f26a144e2afde4f4c6b.gif

Всем спасибо за внимание!

© Habrahabr.ru