У меня есть такой роутер: Nano Pi R1 и я бы хотел собрать для него образ https://freedombox.org/ FreedomBox.
И собирать его я бы хотел на PC.
Вот тут много информации (хотя и не всегда свежей) о сборке и загрузке debian на платформах Allwinner - https://wiki.debian.org/InstallingDebianOn/Allwinner.
Тем, кому не хочется ничего собирать - https://www.armbian.com/nanopi-r1/ и если хочется, но не вдаваясь в подробности - https://github.com/armbian/build

Armbian

При попытке загрузить образ Armbian_20.02.1_Nanopi-r1_buster_current_5.4.20.img система останавливалась при попытке распаковать ядро:

Starting kernel ...

Uncompressing Linux... done, booting the kernel.

В итоге Armbian удалось загрузить так:

  1. Берем официальный образ nanopi-r1_sd_friendlycore-xenial_4.14_armhf_20191219.img. На нем три раздела. Подключаем loop-device и потом монтируем куда-то:
     sudo partx -a -v ./nanopi-r1_sd_friendlycore-xenial_4.14_armhf_20191219.img

  2. Берем образ armbian и также подключаем его как loop-device.
  3. Берем с образа armbian из директории boot файлики zImage и initrd (вернее файлики на которые указывают эти симлинки), а также sun8i-h3-nanopi-r1.dtb и переносим их на официальный образ в раздел boot (заменив старые). Переименовываем initrd - на официальном образе он называется rootfs.cpio.gz. Остальные dtb с официального образа удаляем, во избежание путаницы.
  4. На официальном образе удаляем всё с раздела rootfs.
  5. Переносим всю файловую систему с единственного раздела образа armbian на раздел rootfs официального образа:

    sudo rsync -av ./source ./destination

  6. Отмонтируем loop-устройства и заливаем официальный образ (c ядром, initrd и файловой системой от armbian), на флеху.

Для сборки загружающегося образа я сделал скриптец:

#!/bin/bash
armbian_img='Armbian_20.05.0-trunk_Nanopi-r1_bionic_current_5.4.32.img'
friendlyarm_img='nanopi-r1_sd_friendlycore-xenial_4.14_armhf_20191219.img'

echo 'Copying Original FriendlyARM image...'
cp $friendlyarm_img "Armbian_bootable.img"

mkdir ./original_armbian
mkdir ./bootable_armbian_boot
mkdir ./bootable_armbian_rootfs

armbian_offset=`/sbin/fdisk -lu $armbian_img | grep ${armbian_img}1 | awk '{ print $2}'`

echo "Armbian partition Offset - " $(( $armbian_offset * 512 ))

mount -o loop,offset=$(($armbian_offset * 512)) $armbian_img ./original_armbian

friendlyarm_boot_offset=`/sbin/fdisk -lu $friendlyarm_img | grep ${friendlyarm_img}1 | awk '{ print $2}'`
friendlyarm_rootfs_offset=`/sbin/fdisk -lu $friendlyarm_img | grep ${friendlyarm_img}2 | awk '{ print $2}'`

mount -o loop,offset=$(($friendlyarm_boot_offset * 512)) ./Armbian_bootable.img ./bootable_armbian_boot

echo "Copying kernel..."
cp -L ./original_armbian/boot/zImage ./bootable_armbian_boot/zImage

echo "Copying initrd..."
cp -L ./original_armbian/boot/uInitrd ./bootable_armbian_boot/rootfs.cpio.gz

echo "Copying DTB"
rm -f ./bootable_armbian_boot/sun8i*.dtb
cp ./original_armbian/boot/dtb/sun8i-h3-nanopi-r1.dtb ./bootable_armbian_boot/

umount ./bootable_armbian_boot

mount -o loop,offset=$(($friendlyarm_rootfs_offset * 512)) ./Armbian_bootable.img ./bootable_armbian_rootfs
rm -Rf ./bootable_armbian_rootfs/*

echo "Copying rootfs"
rsync -a ./original_armbian/ ./bootable_armbian_rootfs/
rm -rf ./bootable_armbian_rootfs/boot/*

umount ./bootable_armbian_rootfs
umount ./original_armbian

echo 'Done!'
/home/mike/build/userpatches/config-example.conf

./compile.sh  BOARD=nanopi-r1 BRANCH=dev RELEASE=buster BUILD_MINIMAL=no BUILD_DESKTOP=no KERNEL_ONLY=no KERNEL_CONFIGURE=yes

или так:

./compile.sh  BOARD=nanopi-r1 BRANCH=current RELEASE=buster BUILD_MINIMAL=no BUILD_DESKTOP=no KERNEL_ONLY=no KERNEL_CONFIGURE=no

На NanoPi R1 у меня работает вот так собранный Armbian:

sudo ./compile.sh  BOARD=nanopi-r1 BRANCH=current RELEASE=bionic BUILD_MINIMAL=no BUILD_DESKTOP=no KERNEL_ONLY=no KERNEL_CONFIGURE=no

Сборка ядра и u-boot для Nano Pi R1 (Allwinner H3)

http://wiki.friendlyarm.com/wiki/index.php/Building_U-boot_and_Linux_for_H5/H3/H2%2B
Ставим софт:

apt-get install git swig python-dev python3-dev build-essential bc bison flex u-boot-tools screen gcc-arm-linux-gnueabi libncurses-dev

Распаковываем тулчейн (его можно найти тут):

tar xf arm-cortexa9-linux-gnueabihf-4.9.3-20160512.tar.xz -C /opt/FriendlyARM/toolchain/
export PATH=/opt/FriendlyARM/toolchain/4.9.3/bin:$PATH
export GCC_COLORS=auto
. ~/.bashrc
arm-linux-gcc -v
cd ~
git clone https://github.com/friendlyarm/u-boot.git -b sunxi-v2017.x --depth 1
cd u-boot/
make nanopi_h3_defconfig ARCH=arm CROSS_COMPILE=arm-linux-
make ARCH=arm CROSS_COMPILE=arm-linux-

в результате получится файлик u-boot-sunxi-with-spl.bin, который можно записать на SD-карточку:

dd if=u-boot-sunxi-with-spl.bin of=/dev/sdX bs=1024 seek=8

Вариантов пара - собрать то что предлагает FriendlyARM, либо mainline kernel.
В конце концов, я пришел к тому, что собрать придется оба ядра!
Mainline - новое и хорошее, при его работе (в по крайней мере под qemu) не возникает некоторых ошибок типа:

thermal thermal_zone0: failed to read out thermal zone (-16)

Зато с ядром от FriendlyARM собираются родные для этих устройств файлы DTB.

Ядро от FriendlyARM - 4.14

cd ~
git clone https://github.com/friendlyarm/linux.git -b sunxi-4.14.y --depth 1
cd linux
touch .scmversion
make sunxi_defconfig ARCH=arm CROSS_COMPILE=arm-linux-
make zImage dtbs ARCH=arm CROSS_COMPILE=arm-linux-

Теперь образы ядра и файлики dtb можно скопировать на загрузочный разле флехи:

cp arch/arm/boot/zImage /media/SD/boot/
cp arch/arm/boot/dts/sun8i-*-nanopi-*.dtb /media/SD/boot/

Теперь соберем модули:

cd ~/linux
make modules ARCH=arm CROSS_COMPILE=arm-linux-

и скопируем их на флеху. Считаем, что корневой раздел системы смонтирован в /media/SD/rootfs/:

cd ~/linux
make modules_install INSTALL_MOD_PATH=/media/SD/rootfs/ ARCH=arm CROSS_COMPILE=arm-linux-

Ядро Mainline

git clone https://github.com/torvalds/linux.git -b master --depth 1 mainline_linux
cd mainline_linux

Вот тут написано, что под orangepi ядро надо собирать с помощью arm-linux-gnueabi-, однако у FriendlyARM написано, что с помощью arm-linux- из их тулчейна. Я буду собирать с arm-linux-. Хотя, в чем именно разница - я не знаю, по крайней мере пока.
Для начала - скопируем файлик sunxi_defconfig, который идет с ядром от FriendlyARM, в mainline:

cp ./linux/arch/arm/configs/sunxi_defconfig ./mainline_linux/arch/arm/configs/sunxi_defconfig

Также, в mainline может не быть исходников некоторых модулей. Скопируем их:

cp ./linux/drivers/net/ethernet/allwinner/* ./mainline_linux/drivers/net/ethernet/allwinner/
export PATH=/opt/FriendlyARM/toolchain/4.9.3/bin:$PATH
export GCC_COLORS=auto
ARCH=arm CROSS_COMPILE=arm-linux- make mrproper
make sunxi_defconfig ARCH=arm CROSS_COMPILE=arm-linux-
make ARCH=arm CROSS_COMPILE=arm-linux-

И соберем модули:

make modules ARCH=arm CROSS_COMPILE=arm-linux-

Запуск в эмуляторе

Вот тут страничка qemu-system-arm, посвященная эмуляции OrangePi (который тоже на Allwinner H3): https://www.qemu.org/docs/master/system/arm/orangepi.html
Судя по обсуждениям патчей поддержка эмуляции машин на Allwinner H3 появилась совсем недавно - в конце 2019 года.
Вот тут описан запуск собранного u-boot и ядра:
https://dev.to/rulyrudel/how-to-execute-u-boot-on-qemu-system-arm-2b22
https://pandysong.github.io/blog/post/run_u-boot_in_qemu/

https://www.qemu.org/download/#source

cd ~
apt-get install git build-essential zlib1g-dev pkg-config libglib2.0-dev binutils-dev libboost-all-dev autoconf libtool libssl-dev libpixman-1-dev libpython-dev python-pip python-capstone virtualenv
git clone https://git.qemu.org/git/qemu.git
cd qemu
git submodule init
git submodule update --recursive
./configure
make

Теперь можно посмотреть список машин, который поддерживается и попробывать запустить собранное ядро или u-boot:

cd ~
./qemu/arm-softmmu/qemu-system-arm -machine help | grep orangepi
...
./qemu/arm-softmmu/qemu-system-arm -M orangepi-pc -nic user -nographic \
    kernel ./linux/arch/arm/boot/zImage \
    -append 'console=ttyS0,115200' \
    -dtb ./linux/arch/arm/boot/dts/sun8i-h3-nanopi-r1.dtb

Так как никакой корневой файловой системы у нас нет, то всё закончится так:

.....
[    4.075519] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

Но ядро запустилось!

Сборка образа минимальной системы debian

 cd ~
fallocate -l 4G debian-stable.img
disk='debian-stable.img'
sgdisk --zap-all $disk
sgdisk --mbrtogpt --clear $disk
sgdisk --new=1:2048:+64Mib $disk
sgdisk --typecode=1:8300 $disk
sgdisk -N0 $disk
sgdisk --typecode=2:8300 $disk

Создадим loop-устройства и обнаружим на них партиции:

sudo kpartx -v -a ./debian-stable.img

В выводе будет что-то такое:

add map loop4p1 (253:2): 0 524289 linear 7:4 2048
add map loop4p2 (253:3): 0 7860191 linear 7:4 528384

Отформатируем эти партиции, создадим точки монтирования и смонтируем их!

sudo mkfs.ext4 /dev/mapper/loop4p2
sudo mkfs.ext2 /dev/mapper/loop4p1
mkdir debian-stable
sudo mount  /dev/mapper/loop4p2 ./debian-stable
sudo mkdir ./debian-stable/boot
sudo mount  /dev/mapper/loop4p1 ./debian-stable/boot

Для создания системы я применю Multistrap.

Минимальный конфигурационный файлик Multistrap

[General]
unpack=true
bootstrap=Debian
aptsources=Debian
#cleanup=true

[Debian]
packages=systemd libnss-systemd libpam-systemd dbus default-dbus-session-bus
source=http://ftp.ru.debian.org/debian
keyring=debian-archive-keyring
suite=stable

Теперь на смонтированные разделы нашего файла-образа я залью минимальную систему debian.

sudo multistrap -a armhf -d ./debian-stable -f ./debian-stable.conf

При попытке собрать файловую систему появляется ошибка:

E: The repository 'http://ftp.ru.debian.org/debian buster InRelease' is not signed.  

Причина в том, что в скрипте multistrap некорректно устанавливается значение опции AllowUnauthenticated. Описано тут: https://github.com/volumio/Build/issues/348#issuecomment-462271607
Патчим multistrap:

sudo sed -i 's/Apt::Get::AllowUnauthenticated=true/Acquire::AllowInsecureRepositories=true/g'  /usr/sbin/multistrap

и пробуем снова (в конфигурации должна быть опция keyring=debian-archive-keyring, а noauth=true быть не должно!):

sudo multistrap -a armhf -d ./debian-stable -f ./debian-stable.conf

В результате всё получается и в директории ./debian-stable (куда смонтирован второй раздел файлика-образа) мы наблюдаем корневую файловую систему текущей стабильной версии Debian для архитектуры armhf.

Запускать в chroot исполняемые файлы для архитектуры arm нам позволят ранее установленные в хостовой системе пакеты qemu-user-static, binfmt-support и dpkg-cross.
Подключим /dev (что необходимо для работы с /dev/null и /dev/urandom) и настроим пакеты:

sudo mount -o bind /dev/ ./debian-stable/dev/
sudo LC_ALL=C LANGUAGE=C LANG=C DEBIAN_FRONTEND=noninteractive chroot debian-stable bash -c 'echo "dash dash/sh boolean false" | debconf-set-selections &&  dpkg --configure -a'

Для настройки некоторых пакетов нужно задать пароль root:

sudo chroot debian-stable/ passwd

Теперь донастроим оставшиеся пакеты:

sudo LC_ALL=C LANGUAGE=C LANG=C DEBIAN_FRONTEND=noninteractive chroot debian-stable dpkg --configure -a

Теперь скопируем ядро и dtb:

sudo cp ./mainline_linux/arch/arm/boot/zImage ./debian-stable/boot/
sudo cp ./mainline_linux/arch/arm/boot/dts/sun8i-h3-nanopi-r1.dt* ./debian-stable/boot/

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

cd ./mainline_linux
sudo PATH=/opt/FriendlyARM/toolchain/4.9.3/bin:$PATH make modules_install INSTALL_MOD_PATH=../debian-stable ARCH=arm CROSS_COMPILE=arm-linux-

Теперь можно сделать файлик /etc/fstab. Для этого - посмотрим UUID партиций и создадим /etc/fstab:

blkid /dev/mapper/loop4p1
/dev/mapper/loop4p1: UUID="85b026f4-afd7-4ecf-8679-dd0c87e628bb" TYPE="ext2" PARTUUID="f9c59bb5-1bde-441b-8e5a-9eeff8e77693"
blkid /dev/mapper/loop4p2
/dev/mapper/loop4p2: UUID="683177df-8d27-4733-a490-c8e69fb0b525" TYPE="ext4" PARTUUID="9faf1102-5994-4226-ac73-adc6b6e4e043"

В итоге /etc/fstab будет такой:

UUID=683177df-8d27-4733-a490-c8e69fb0b525   /      ext4   defaults,discard,noatime,nodiratime   0   1
UUID=85b026f4-afd7-4ecf-8679-dd0c87e628     /boot  ext2   defaults,discard,noatime,nodiratime   0   1

Заменим дефолтный target:

sudo rm -f ./debian-stable/etc/systemd/system/default.target
sudo ln -s /lib/systemd/system/multi-user.target ./debian-stable/etc/systemd/system/default.target

И создадим симлинк для того, чтобы появилось устройство ttyS0:

sudo ln -s /lib/systemd/system/getty@.service ./debian-stable/etc/systemd/system/getty.target.wants/getty@ttyS0.service

Если этого не сделать - будут ошибки типа:

[  *** ] A start job is running for /dev/ttyS0 (1min 29s / 1min 30s)
[ TIME ] Timed out waiting for device /dev/ttyS0.
[DEPEND] Dependency failed for Serial Getty on ttyS0.
cd ~
sudo umount ./debian-stable/boot
sudo umount ./debian-stable

Удалим loop-устройства:

sudo kpartx -d ./debian-stable.img

И попробуем запуститься с ядром mainline и dtb из поставки ядра от FriendlyARM!

./qemu/arm-softmmu/qemu-system-arm -M orangepi-pc \
-nic user -nographic -kernel ./mainline_linux/arch/arm/boot/zImage  \
-append 'console=ttyS0,115200 root=/dev/mmcblk0p2' \
-dtb ./linux/arch/arm/boot/dts/sun8i-h3-nanopi-r1.dtb \
-sd ./debian-stable.img

В итоге - не смотря на некоторые ошибки с сервисами systemd, система смогла загрузиться, а я смог в нее залогиниться с паролем, заданным на этапе создания образа.

Самым логичным способом, чтобы настройки загрузки на флехе соотвествовали настройкам U-Boot в железке, было бы взять образ флехи от производителя (например с ubuntu xenial), подмонтировать его и заменить файлик ядра и корневую файловую систему.
Я так и поступил.

Но можно пойти трудным путем и пытаться сделать все вручную.

Судя по начальным сообщениям:

DRAM: 1024 MiB(408MHz)
CPU Freq: 408MHz
memory test: 1
Pattern 55aa  Writing...Reading...OK
Trying to boot from MMC2
Boot device: emmc


U-Boot 2017.11 (Oct 18 2019 - 02:50:31 +0800) Allwinner Technology

CPU:   Allwinner H3 (SUN8I 1680)
Model: FriendlyElec NanoPi H3
DRAM:  1 GiB
CPU Freq: 1008MHz
MMC:   SUNXI SD/MMC: 1, SUNXI SD/MMC: 0
*** Warning - bad CRC, using default environment

И судя по тому, что начинает загружаться предустановленная система - я что-то сделал не так.
Наверное надо взять официальный образ и посмотреть что внутри.
Кстати, в выводе printenv некоторые особенности.

arch=arm
baudrate=115200
board=nanopi-r1
board_name=sunxi
boot_a_script=load ${devtype} ${devnum}:${distro_bootpart} ${scriptaddr} ${prefix}${script}; source ${scriptaddr}
boot_efi_binary=if fdt addr ${fdt_addr_r}; then bootefi bootmgr ${fdt_addr_r};else bootefi bootmgr ${fdtcontroladdr};fi;load ${devtype} ${devnum}:${distro_bootpart} ${kernel_addr_r} efi/booti
boot_extlinux=sysboot ${devtype} ${devnum}:${distro_bootpart} any ${scriptaddr} ${prefix}extlinux/extlinux.conf
boot_mmc=2
boot_net_usb_start=usb start
boot_prefixes=/ /boot/
boot_script_dhcp=boot.scr.uimg
boot_scripts=boot.scr.uimg boot.scr
boot_targets=fel mmc_auto usb0 pxe dhcp 
bootcmd=fatload mmc 0:1 ${scriptaddr} boot.scr; source ${scriptaddr}
bootcmd_dhcp=run boot_net_usb_start; if dhcp ${scriptaddr} ${boot_script_dhcp}; then source ${scriptaddr}; fi;setenv efi_fdtfile ${fdtfile}; if test -z "${fdtfile}" -a -n "${soc}"; then sete;
bootcmd_fel=if test -n ${fel_booted} && test -n ${fel_scriptaddr}; then echo '(FEL boot)'; source ${fel_scriptaddr}; fi
bootcmd_mmc0=setenv devnum 0; run mmc_boot
bootcmd_mmc1=setenv devnum 1; run mmc_boot
bootcmd_mmc_auto=run bootcmd_mmc0
bootcmd_pxe=run boot_net_usb_start; dhcp; if pxe get; then pxe boot; fi
bootcmd_usb0=setenv devnum 0; run usb_boot
bootdelay=2
bootm_size=0xa000000
console=ttyS0,115200
cpu=h3
dfu_alt_info_ram=kernel ram 0x42000000 0x1000000;fdt ram 0x43000000 0x100000;ramdisk ram 0x43300000 0x4000000
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
efi_dtb_prefixes=/ /dtb/ /dtb/current/
ethaddr=02:81:8a:99:42:c5
fdt_addr_r=0x43000000
fdtcontroladdr=7bf4fa48
fdtfile=sun8i-h3-nanopi-m1-plus.dtb
kernel_addr_r=0x42000000
load_efi_dtb=load ${devtype} ${devnum}:${distro_bootpart} ${fdt_addr_r} ${prefix}${efi_fdtfile}
mmc_boot=if mmc dev ${devnum}; then setenv devtype mmc; run scan_dev_for_boot_part; fi
mmc_bootdev=1
preboot=usb start
pxefile_addr_r=0x43200000
ramdisk_addr_r=0x43300000
scan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;run scan_dev_for_efi;
scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${die
scan_dev_for_efi=setenv efi_fdtfile ${fdtfile}; if test -z "${fdtfile}" -a -n "${soc}"; then setenv efi_fdtfile ${soc}-${board}${boardver}.dtb; fi; for prefix in ${efi_dtb_prefixes}; do if te
scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}extlinux/extlinux.conf; then echo Found ${prefix}extlinux/extlinux.conf; run boot_extlinux; echo SCRIPT FAILi
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_scre
scriptaddr=0x43100000
serial#=02c000818a9942c5
soc=sunxi
stderr=serial
stdin=serial,usbkbd
stdout=serial
usb_boot=usb start; if usb dev ${devnum}; then setenv devtype usb; run scan_dev_for_boot_part; fi
wifi_mac_node=[2 c5 42 99 8a 81]

Во-первых - DTB не от nanopi-r1, а sun8i-h3-nanopi-m1-plus.dtb

Enter your comment. Wiki syntax is allowed:
K᠎ X᠎ D J J
 
  • linux_faq/сборка_системы_для_arm-роутера_на_pc.txt
  • Last modified: 2020/05/23 22:28
  • by admin