Автосборка Fsbl, U-Boot, linux kernel и установка debian для amd64 для Zynq Ultrascale zcu106

Цели статьи

  • Автоматизировать скриптами сборку загрузчиков и ядра Linux с заданными конфигурационными файлами в автоматическом режиме без необходимости запуска gui Vivado;

  • Автоматизировать установку операционной системы Debian из бинарных файлов с заданными пакетами и первоначальными настройками;

  • Загружать образы ядра linux + dts по tftp, а корневую файловую систему по NFS для сохранения ресурса карточки и времени на копирование файлов с рабочей станции на устройство;

  • Добавить в U-Boot меню для быстрого выбора источника загрузки: всё с карточки, всё по сети и разные комбинации этих вариантов;

  • При необходимости данные скрипты можно адаптировать практически под любую встраиваемую платформу.

Введение

Операционная система Debian была выбрана по причине использования окружения для активной разработки, где основными критериями являются: стабильность, легковесность, а главное — возможность быстрой установки пакетов при необходимости. По завершению разработки в случаях, когда под хранение выделяется только nand или nor флешка ограниченного объёма, делаем сборку buildroot с уже определённым минимальным набором пакетов.

Установка необходимых программ

Вся работа проводилась на компьютере с операционной системой Debian, для установки используется стандартный менеджер пакетов. Для сборки fsbl и pmu необходимо установить Vivado 2020 и старше. Всё отлично работает с самой последней 2023.2

git clone https://github.com/Igorbunow/build-uboot-linux-debian.git
apt install gcc-aarch64-linux-gnu

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

apt install debootstrap atftpd nfs-kernel-server qemu-user-static fdisk
mkdir /srv
mkdir /srv/tftp
chown 777 /srv/tftp

vim  /etc/default/atftpd

## Options for atftpd:
USE_INETD=false
OPTIONS="--port 69 --tftpd-timeout 300 --retry-timeout 5 --mcast-port 1758 --mcast-addr 239.239.239.0-255 --mcast-ttl 1 --maxthread 100 --verbose=5 /srv/tftp"

systemctl restart atftpd
mkdir /srv/nfs
mkdir /srv/nfs/root

vim /etc/exports

#/srv/nfs   *(no_root_squash,no_subtree_check,rw)
/srv/nfs   192.168.10.1/24(no_root_squash,no_subtree_check,rw)
#/tmp/root *(no_root_squash,no_subtree_check,rw)

Крайне не рекомендуется давать всем хостам права (указывать *), т.к. кто угодно может из сети может положить исполняемый файл от локального администратора с установленным битом SUID с опцией no_root_squash, которая отключает понижение прав root при подключении к NFS, но она необходима для корректной работы подключенной папки файловой системы в качестве корневой.

Собираем загрузчик FSBL+U-Boot и ядро Linux

Все скрипты для сборки загрузчиков и ядра находятся в папке ./boot репозитория:

configs

папка с defconfig для linux и uboot

all.sh

Скрипт, включающий все скрипты ниже и делающий полную сборку

download_orig.sh

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

fsbl_pmu_2020.sh

Скрипт, создающий проект по умолчанию в Vitis и собирающий первичный загрузчик и pmu (Требуется Vivado, Vitis от 2020)

dts.sh

Скрипт, собирающий утилиту для работы с деревом устройств для ядра linux и u-boot (для компьютера), необходимую для дальнейшей сборки

atf.sh

Скрипт для сборки ARM trusted firmware (требуется кросскомпилятор или тулчейн)

u-boot.sh

Скрипт для сборки загрузчика U-Boot

kernel.sh

Скрипт для сборки ядра Linux

bootbin.sh

Копирование собранного первичного загрузчика, U-Boot, pmu и bl31 с последующей сборкой готового загрузочного образа BOOT.bin

bootscript.sh

Генерирование скрипта для загрузчика UBoot из boot.script

image.sh

Копирование образа загрузчика BOOT.bin, ядра linux, device-tree, скрипта UBoot, модулей ядра в виде, пригодном для переноса на загрузочный раздел SD карточки. На этот же раздел кладём system.bit, собранный под вашу задачу. Модули ядра переносятся в rootfs

Настойка ядра Linux и UBoot

При сборке система берет defconfig, расположенные в папках ./configs/linux/xilinx_ulrascale_debug_defconfig и ./configs/uboot/xilinx_ulrascale_debug_defconfig и создаёт из них соответствующие .config файлы. Если Вам необходимо сделать настройки под свою задачу, заходим в папку u-boot-xlnx или linux-xlnx, настраиваем:

make ARCH=arm64 menuconfig

И сохраняем. Затем создаём из полученного .configdefconfig:

make ARCH=arm64 savedefconfig

Забираем из корня u-boot-xlnx или linux-xlnx defconfig, переименовываем, в зависимости от того, что у нас и кладём соответственно в /xilinx_ulrascale_debug_defconfig или ./configs/uboot/xilinx_ulrascale_debug_defconfig.

Загрузочного скрипта UBoot

Данный скрипт выполняется UBoot после загрузки переменных окружения, которые можно хранить, например, на карточке SD. Скрипт поддерживает циклы и операторы условного перехода, синтаксис похож на синтаксис bash. С его помощью в зависимости от заданных переменных, в нашем случае ip адресов tftp или nfs серверов и их папок, сделано отображение пунктов меню с соответствующими вариантами загрузки:

479c81d727157780d4204a6aa6fdb1b9.pngboot.script

setenv bitsteam_name system.bit
setenv kernel_image_name Image
setenv dts_name zynqmp-zcu106-revA.dtb
setenv bitsteam_addr 0x20000000
setenv kernel_image_addr 0x10000000
setenv dts_addr 0x02a00000
setenv load_tftp_bitsteam 'dhcp ${bitsteam_addr} ${tftp_serverip}:${tftp_dir}${bitsteam_name}; fpga load 0 ${bitsteam_addr} $filesize;'
setenv load_tftp_kernel_image 'dhcp ${kernel_image_addr} ${tftp_serverip}:${tftp_dir}${kernel_image_name}'
setenv load_tftp_dts 'dhcp ${dts_addr} ${tftp_serverip}:${tftp_dir}${dts_name}'
setenv load_mmc_bitsteam 'fatload mmc 0:1 ${bitsteam_addr} ${bitsteam_name}; fpga load 0 ${bitsteam_addr} $filesize;'
setenv load_mmc_kernel_image 'fatload mmc 0 ${kernel_image_addr} ${kernel_image_name}'
setenv load_mmc_dts 'fatload mmc 0 ${dts_addr} ${dts_name}'
setenv boot_dev booti 0x10000000 - 0x02a00000
setenv bootargs_mmc 'earlycon clk_ignore_unused consoleblank=0 root=/dev/mmcblk0p2 rootfstype=btrfs rw rootwait uio_pdrv_genirq.of_id=generic-uio net.ifnames=0 biosdevname=0'
setenv bootargs_nfs 'earlycon clk_ignore_unused consoleblank=0 root=/dev/nfs ip=dhcp nfsroot='${nfs_serverip}':'${nfs_dir}',nolock,nfsvers=4 rootfstype=nfs rw rootwait uio_pdrv_genirq.of_id=generic-uio net.ifnames=0 biosdevname=0'

setenv bootcmd bootmenu 10

setenv bootmenu_0 Load All from MMC='setenv bootargs '${bootargs_mmc}';run load_mmc_bitsteam; run load_mmc_kernel_image; run load_mmc_dts; run boot_dev;'


if test -n $tftp_serverip;
then
	if test -n $nfs_serverip;
	then
		setenv root_name NFS
		setenv bootargs ${bootargs_nfs}
	else
		setenv root_name SD_card
		setenv bootargs ${bootargs_mmc}
	fi
	setenv bootmenu_1 Load All via tftp ${tftp_serverip} root ${root_name}='run load_tftp_bitsteam; run load_tftp_kernel_image; run load_tftp_dts; run boot_dev;'
	setenv bootmenu_2 Load bitsteam via tftp ${tftp_serverip} kernel from SD card root ${root_name}='run load_tftp_bitsteam; run load_mmc_kernel_image; run load_mmc_dts; run boot_dev;'
	setenv bootmenu_3 Load bitsteam from SD Card  kernel via tftp ${tftp_serverip} root ${root_name}='run load_mmc_bitsteam; run load_tftp_kernel_image; run load_tftp_dts; run boot_dev;'
	setenv bootmenu_4 Reset board=reset
	setenv bootmenu_5 Test='ls'
else
	setenv bootmenu_1 Reset board=reset
fi

bootmenu 5

Переменные c ip адресами необходимо задать до загрузки скрипта. О том, как это сделать, будет описано ниже.

Также, в случае необходимости, можно требуемым образом изменить аргументы загрузки bootargs для bootargs_mmc и bootargs_nfs. `net.ifnames=0 biosdevname=0` необходимо для запрета переименования eth0 → end0, т.к. при монтировании по nfs переименования не происходит и этот запрет позволяет избегать создания разных версий дополнительных конфигов rootfs.

Настраиваем кросскомпиляцию

Если вы используете внешний toolchain, добавляем в скриптах: fsbl_pmu_2020.sh, kernel.sh, u-boot.sh путь до его /bin, префикс кросскомпиляции и архитектуру:

export PATH=/tmp/build/buildroot/output/host/bin:${PATH}
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

Запускаем сборку

Запускаем скрипт ./all.sh и ждём завершения сборки. Если всё сделано правильно, то в папке ./image у нас будут следующие файлы, готовые для копирования на загрузочный раздел карты памяти за исключением модулей ядра — их копируем в rootfs

modules

Папка с модулями ядра Linux. Предназначена для копирования на rootfs раздел скриптами ниже

BOOT.bin

Образ загрузчика, содержащий fsbl, pmu, bl31, UBoot

boot.scr

Стартовый скрипт загрузчика UBoot

Image

Ядро Linux

zynqmp-zcu106-revA.dtb

Дерево устройств ядра linux

system.bit

Битстрим для fpga, подготавливается отдельно

Собираем Debian из бинарных пакетов

Сборка debian также полностью автоматизирована при помощи скриптов. RootFs debian собирается в папке ./root. Переходим в папку debian:

files

Файлы, которые необходимо поместить в целевую систему с заменой существующих

2_debian_bootstrap.sh

Скрипт, выполняющий скачивание пакетов debian и производящий их первичную настройку при помощи debootstrap

3_copy_kernel_modules.sh

Скрипт, выполняющий копирование собранных выше модулей ядра в rootfs debian

4_copy_and_config.sh

Завершающие настройки системы: задание пароля root, создание пользователя, настройки монтирования и сети

  • Добавляем дополнительные пакеты, убираем существующие в зависимости от вашей задачи. Для этого в скрипте 2_debian_bootstrap.sh задаём переменной PACKAGES список соответствующих пакетов. При необходимости можно изменить версию систему, разрядность, источник пакетов. А также, при необходимости, можно вместо debian собрать ubuntu

  • Проводим окончательную настройку системы. Для этого в скрипте 4_copy_and_config.sh задаём требуемый пароль root, создание дополнительного пользователя, настройку сети, монтирования по-умолчанию fstab, копирование требуемых файлов из папки files, очистку кэша пакетов и логов и любые другие требуемые дополнительные настройки

  • По завершению настройки последовательно выполняем скрипты:

./2_debian_bootstrap.sh
./3_copy_kernel_modules.sh
./4_copy_and_config.sh

и получаем в папке ./root полностью готовую rootfs с debian, содержащую модули ядра для дальнейшего разворачивания на устройстве.

Работа c rootfs

Представим следующую ситуацию. Дождавшись, наконец, завершения сборки debian вы вдруг обнаруживаете, что данный образ не вписался в заданный объём, или вы забыли установить какой-то пакет. Что делать в таком случае? К счастью, заново сборку запускать не нужно, нас выручает qemu-static, производящий эмуляцию пользовательского режима. В этом режиме QEMU может запускать процессы Linux, скомпилированные для одного ЦП, на другом ЦП. Этот режим можно использовать как один из способов кроссборки с некоторыми ограничениями. Самым быстрым, при этом является вариант с использованием нативного кроскомпилятора напрямую, а в данном случае всё же работает через прослойку эмуляции

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

ln -s "$(which qemu-arm64-static)" ./root/qemu-arm64-static
  • Монтирум системные устройства в rootfs целевого устройства (если хотите просто доустановить пакеты, то данный шаг можно пропустить):

mount --bind /dev ./root/dev/
mount --bind /sys ./root/sys/
mount --bind /proc ./root/proc/
mount --bind /dev/pts ./root/dev/pts
chroot ./root
PACKAGES="valgrind build-essential clang u-boot-tools cmake git subversion \
          tcpdump kbuild nmap wget libboost-all-dev linux-headers-arm64 \
          minicom picocom p7zip-full gzip zstd bzip2"
apt update
apt install ${PACKAGES}
echo "packages: ${PACKAGES}" >> /info
apt clean
  • Далее, можно зайти под user через login или `sudo -u user bash`, собрать, требуемые программы и выйти `exit`

  • Выходим из chroot:

exit
umount ./root/sys
umount ./root/proc
umount ./root/dev/pts
umount ./root/dev
  • В случае известных багов, мешающих запуску некоторых служб, в частности binfmt.service чиним это:

rm -rf ./root/usr/lib/binfmt.d/python3.11.conf 
rm -rf ./root/usr/lib/binfmt.d/llvm-14-runtime.binfmt.conf
rm -rf ./root/var/log/apt/*
echo -n > ./root/var/log/alternatives.log
echo -n > ./root/var/log/dpkg.log
echo -n > ./root/root/.bash_history
rm ./root/var/cache/apt/archives/lock
  • Дописываем в ./root/info дополнительную иформацию о системе, помимо сгенерированной системое, например, расшифрем, что stable (12.0 bookworm), чтобы не вспоминать через несколько лет, что за система лежит в образе

Создаём образ для карты SD памяти

Для передачи образа карты памяти и его последующего хранения, создадим минимально необходимый образ системы, который, при разворачивании на карту памяти будет расширяться до его максимального размера. В качестве файловой системы для корневой файловой системы мы выбрали btrfs — система, поддерживающая прозрачное сжатие и копирование при записи, что продлевает жизнь карточкам памяти либо иному флеш носителю, записывая меньше информации и благодаря тому, что дважды в одно место данные не пишутся, производится выравнивание ресурса. Если по каким-то причинам необходимо использовать ext2, ext3, ext4 системы — как это сделать, тоже будет описано ниже.

Оцениваем необходимый размер образа

  • Загрузочный размер может иметь размер от 32Mb до 4Гб. 32Мб будет совсем впритык, а 4Гб — слишком много. Размер выбирается в зависимости от задач и размещаемых на нём файлах. Выберем 256Мб

  • Размер корневой файловой системы. Смотрим, сколько у нас получилось в образе, который мы собираемся записывать. В качестве примера, расмотрим минимальный образ без дополнительных пакектов. Смотрим:

du -h -d 0
517M

Соответственно, выбираем, 640Мб под корневой раздел

Создаём пустой образ необходимого размера

Выше мы определили, что размер нашего образа составляет 768Мб. Создадим пустой файл такого размера:

dd if=/dev/zero bs=1M count=768 of=ultrascale_short.img
sync;

и дожидаемся успешного создания:

768+0 records in
768+0 records out
805306368 bytes (805 MB, 768 MiB) copied, 0.396911 s, 2.0 GB/s

Монтируем и размечаем образ

fdisk -c=dos ultrascale_short.img

Затем последовательно выполняем команды. Размер указываем в секторах по 512 байт:

n

создаём новый раздел (загрузочный)

p

указываем тип MBR раздела — первичный

1

Указываем номер загрузочного раздела (строго 1-ый для загрузочного)

63

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

262144

Последний сектор раздела, вычисляем для 128Мб: 128×2^20/512

a

Делаем раздел загрузочным

n

создаём новый раздел (rootfs)

p

указываем тип MBR раздела — первичный

2

Указываем номер раздела rootfs

262145

1-ый сектор раздела rootfs, оставляем по-умолчанию

1572863

Последний сектор раздела rootfs

w

Записываем изменения в файл и выходим

лог выполнения fdisk

fdisk -c=dos ultrascale_short.img

Welcome to fdisk (util-linux 2.39.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
DOS-compatible mode is deprecated.

Created a new DOS (MBR) disklabel with disk identifier 0xb315f728.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (63-1572863, default 63): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (63-1572863, default 1572863): 262144

Created a new partition 1 of type 'Linux' and of size 128 MiB.

Command (m for help): a
Selected partition 1
The bootable flag on partition 1 is enabled now.

Command (m for help): n
Partition type
   p   primary (1 primary, 0 extended, 3 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (2-4, default 2): 2
First sector (262145-1572863, default 262145): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (262145-1572863, default 1572863): 

Created a new partition 2 of type 'Linux' and of size 640 MiB.

Command (m for help): w
The partition table has been altered.
Syncing disks.
sync;
losetup --partscan --find --show ultrascale_short.img

и дожидаемся ответа, каким устройством смонтировалось:

/dev/loop0

Для избежания проблем, т.к. у вас могут определиться по-другому, будем обозначать loop0 как loopX. При необдуманном копировании возможна потеря данных. Особенно славится в этом отношении команда dd, гарантированно затирающая данные на диски, если ошибиться с буквой диска и ещё подождать при этом…

Смотрим определившиеся разделы:

ls /dev | grep loopX

и видим наши 2 раздела:

loop0
loop0p1
loop0p2
dd if=/dev/zero of=/dev/loopXp1 bs=4M
dd if=/dev/zero of=/dev/loopXp2 bs=4M
sync;

Лог очистки разделов loopXp1 и loopXp2

dd if=/dev/zero of=/dev/loop0p1 bs=4M
dd if=/dev/zero of=/dev/loop0p2 bs=4M
sync;
dd: error writing '/dev/loop0p1': No space left on device
32+0 records in
31+0 records out
134185984 bytes (134 MB, 128 MiB) copied, 0.617296 s, 217 MB/s
dd: error writing '/dev/loop0p2': No space left on device
160+0 records in
159+0 records out
671088128 bytes (671 MB, 640 MiB) copied, 4.38618 s, 153 MB/s

Появление ошибок о том, что закончилось место на диске вполне нормально и объяснимо, тк dd не знает размер диска и пишет до тех пор, пока не закончится место на разделе.

Форматируем загрузочный раздел в fat, а rootfs в файловую систему btrfs:

mkfs.vfat -F 32 -n "BOOT" /dev/loopXp1
mkfs.btrfs /dev/loopXp2 -L "root"
sync;

Лог форматирования разделов:

mkfs.vfat -F 32 -n "BOOT" /dev/loop0p1
mkfs.btrfs /dev/loop0p2 -L "root"
sync;
mkfs.fat 4.2 (2021-01-31)
btrfs-progs v6.3.2
See https://btrfs.readthedocs.io for more information.

Performing full device TRIM /dev/loop0p2 (640.00MiB) ...
NOTE: several default settings have changed in version 5.15, please make sure
      this does not affect your deployments:
      - DUP for metadata (-m dup)
      - enabled no-holes (-O no-holes)
      - enabled free-space-tree (-R free-space-tree)

Label:              root
UUID:               553f75fd-bc80-4553-8c7c-279c4e38a6a6
Node size:          16384
Sector size:        4096
Filesystem size:    640.00MiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP              32.00MiB
  System:           DUP               8.00MiB
SSD detected:       yes
Zoned device:       no
Incompat features:  extref, skinny-metadata, no-holes, free-space-tree
Runtime features:   free-space-tree
Checksum:           crc32c
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1   640.00MiB  /dev/loop0p2

Если всё же выбрали ext4, форматируем следующим образом (не забывая при этом поправить в boot.script в bootargs_mmc тип корневой файловой системы на rootfstype=ext4):

mkfs.vfat -F 32 -n "BOOT" /dev/loopXp1
mkfs.ext4 /dev/loopXp2 -L "root"
sync;
mkdir /tmp/root
mkdir /tmp/boot
mount -o compress=lzo /dev/loop0p2 /tmp/root
mount  /dev/loop0p1 /tmp/boot

Копируем собранные загрузчики и rootfs в примонтированные разделы образа

  • Копируем bitstream system.bit в /tmp/boot

  • Копируем загрузчик, ядро linux, dts и скрипт U-Boot

cp ./../boot/image/BOOT.bin  /tmp/boot
cp ./../boot/image/boot.scr  /tmp/boot
cp ./../boot/image/Image /tmp/boot
cp ./../boot/image/zynqmp-zcu106-revA.dtb /tmp/boot
chmod -R 777 /tmp/boot
sync;
cp -rpna  ./root/*  /tmp/root/
rm /tmp/root/qemu-arm64-static
sync;

Если наша корневая системы была заархивирована:

tar -C /tmp/root -xjf images/rootfs.tar.bz2
sync;
umount /tmp/boot
umount /tmp/root
sync;
losetup -d /dev/loopX
sync;

Сжимаем полученный образ и записываем его на SD карту

  • сжимаем образ

    Для дальнейшего хранения образа и передачи его другим разработчикам, удобнее всего его будет сжать. Для сжатия выберем формат gzip, тк сжатый им диск понимают многие утилиты для записи образов дисков, в том числе и популярный rufus. Другой формат zstd позволяет сжать лучше, но применяйте его, если уверены, что кому его передаёте будет его удобно использовать

gzip -9cf ultrascale_short.img > ultrascale_short.img.gz
zstd -16v --ultra --format=zstd ultrascale_short.img -o ultrascale_short.img.zst

В нашем случае получилось следующее:

ultrascale_short.img.gz

202Mb

ultrascale_short.img.zst

168Mb

zcat ultrascale_short.img.gz | dd bs=8M iflag=fullblock of=/dev/sdxxx status=progress; sync;
zstdcat ultrascale_short.img.zst | dd bs=8M iflag=fullblock of=/dev/sdxxx status=progress; sync;

Лог записи образа sd карты

zcat ultrascale_short.img.gz | dd bs=8M iflag=fullblock of=/dev/sdf status=progress; sync;
754974720 bytes (755 MB, 720 MiB) copied, 5 s, 150 MB/s
96+0 records in
96+0 records out
805306368 bytes (805 MB, 768 MiB) copied, 129.194 s, 6.2 MB/s
  • Если лицо, которому передаёте образ, использует windows, то gzip образ можно записать напрямую через rufus без распаковки:

92390411e9d33b7d900efbe8489e5129.png

Первый запуск устройства

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

growpart /dev/mmcblk0 2
btrfs filesystem resize max /
sync;
  • для ext2, ext3, ext4:

growpart /dev/mmcblk0 2
resize2fs /dev/mmcblk0p2
sync;
  • для xfs:

growpart /dev/mmcblk0 2
xfs_growfs /
sync;

и перезагружаем устройство

chattr +i /lib/systemd/system/serial-getty@.service

Загрузка ядра Linux, dts, bitstream по tftp, rootfs debian по NFS

  • Настраиваем tftp и NFS как было описано выше

  • Не дожидаясь выполнения загрузочного скрипта uboot, сразу при включении устройства при появлении обратного отсчёта прерываем загрузку устройства клавишей enter:

201d7829003fafba0a5c6ff686a4fda4.png

  • и попадаем в терминал U-Boot, в котором указываем ip fttp сервера и путь к файлам, относительно корня сервера:

setenv tftp_serverip '192.168.4.12'
setenv tftp_dir /zsu106/
saveenv
reset

Перезагружаемся и видим, что появились пункты меню, позволяющие загрузить ядро Linux, dts, bitstream по tftp, а rootFS debian — с карты памяти:

4882c105a33d913a059fe5e974beab72.png

  • Загружаем все по сети: ядро Linux, dts, bitstream по tftp, а rootFS debian — по NFC

    Прерываем загрузку UBoot как в случае с tftp и прописываем ip и путь к папке с rootfs debian:

setenv nfs_serverip '192.168.4.12'
setenv nfs_dir /tmp/root
saveenv
reset

82860d0663dda521d5bb31531a3669db.png

Весь процесс загрузки подробнее на видео:

setenv tftp_serverip
setenv nfs_serverip
  • Никогда не сохраняйте переменные окружения после загрузки скрипта, иначе меню загрузки будет отображаться некорректно! Если всё же это сделали — то извлеките карту памяти и удалите с загрузочного раздела сохранённые файлы окружения: uboot-redund.env и uboot.env

Материалы к статье:

1) Репозиторий со скриптами: https://github.com/Igorbunow/build-uboot-linux-debian.git

2) Минималистичный загрузочный образ: https://disk.yandex.ru/d/odFFJr8C_YtFhQ

© Habrahabr.ru