Vytvorenie obrazu Ubuntu pre ARM „od základov“

Keď sa vývoj len začína, často ešte nie je jasné, aké balíky pôjdu do cieľového rootfs.

Inými slovami, brať do úvahy LFS, buildroot alebo yocto (alebo niečo iné) je ešte predčasné, ale začínať už treba. Pre bohatých (mám na pilotných vzorkách 4GB eMMC) je možné poskytnúť vývojárom distribúciu, ktorá dovolí rýchlo dodať to, čo práve chýba, a potom môžeme vždy zostaviť zoznam balíkov a vytvoriť zoznam pre cieľový rootfs.

Tento článok nenesie novosť a predstavuje jednoduchý copy-paste návod.

Cieľom článku je zostaviť Ubuntu rootfs pre ARM dosky (v mojom prípade na báze Colibri imx7d).

Zostavenie obrazu

Zbierame cieľový rootfs pre reprodukciu.

Rozbaľujeme Ubuntu Base

Verziu si vyberáme sami na základe potreby a vlastných preferencií. Tu som uviedol 20.

$ mkdir ubuntu20
$ cd ubuntu20
$ mkdir rootfs
$ wget http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/ubuntu-base-20.04-base-armhf.tar.gz
$ tar xf ubuntu-base-20.04-base-armhf.tar.gz -C rootfs

Kontrola podpory BINFMT v jadre

Ak máte rozšírenú distribúciu, podpora BINFMT_MISC je aktivovaná a všetko je nastavené, ak nie — som si istý, že viete, ako aktivovať podporu BINFMT v jadre.

Uistite sa, že BINFMT_MISC je zapnuté v jadre:

$ zcat /proc/config.gz | grep BINFMT
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_BINFMT_MISC=y

Teraz musíme skontrolovať nastavenia:

$ ls /proc/sys/fs/binfmt_misc
qemu-arm  register  status
$ cat /proc/sys/fs/binfmt_misc/qemu-arm
enabled
interpreter /usr/bin/qemu-arm
flags: OC
offset 0
magic 7f454c4601010100000000000000000002002800
mask ffffffffffffff00fffffffffffffffffeffffff

Registráciu manuálne je možné vykonať napríklad pomocou tohto návodu.

Nastavenie qemu static arm

Teraz budeme potrebovať staticky zostavený exemplár qemu.

!!! POZOR!!!
Ak plánujete použiť kontajner na zostavenie niečoho, pozrite sa:
https://sourceware.org/bugzilla/show_bug.cgi?id=23960
https://bugs.launchpad.net/qemu/+bug/1805913
Potom pre x86_64 host a arm guest je potrebné použiť i386 verziu qemu:
http://ftp.ru.debian.org/debian/pool/main/q/qemu/qemu-user-static_5.0-13_i386.deb

$ wget http://ftp.debian.org/debian/pool/main/q/qemu/qemu-user-static_5.0-13_amd64.deb
$ alient -t qemu-user-static_5.0-13_amd64.deb
# cesta v rootfs a názov spustiteľného súboru musia byť rovnaké ako /proc/sys/fs/binfmt_misc/qemu-arm
$ mkdir qemu
$ tar xf qemu-user-static-5.0.tgz -C qemu
$ file qemu/usr/bin/qemu-arm-static
qemu/usr/bin/qemu-arm-static: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), staticky prepojené, BuildID[sha1]=be45f9a321cccc5c139cc1991a4042907f9673b6, pre GNU/Linux 3.2.0, odstránené
$ cp qemu/usr/bin/qemu-arm-static rootfs/usr/bin/qemu-arm
$ file rootfs/usr/bin/qemu-arm
rootfs/usr/bin/qemu-arm: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), staticky prepojené, BuildID[sha1]=be45f9a321cccc5c139cc1991a4042907f9673b6, pre GNU/Linux 3.2.0, odstránené

Chroot

Jednoduchý skript:

ch-mount.sh

#!/bin/bash

function mnt() {
    echo "MOUNTING"
    sudo mount -t proc /proc ${2}proc
    sudo mount --rbind /sys ${2}sys
    sudo mount --make-rslave ${2}sys
    sudo mount --rbind /dev ${2}dev
    sudo mount --make-rslave ${2}dev
    sudo mount -o bind /dev/pts ${2}dev/pts
    sudo chroot ${2}
}

function umnt() {
    echo "UNMOUNTING"
    sudo umount ${2}proc
    sudo umount ${2}sys
    sudo umount ${2}dev/pts
    sudo umount ${2}dev

}

if [ "$1" == "-m" ] && [ -n "$2" ] ;
then
    mnt $1 $2
elif [ "$1" == "-u" ] && [ -n "$2" ];
then
    umnt $1 $2
else
    echo ""
    echo "Either 1'st, 2'nd or both parameters were missing"
    echo ""
    echo "1'st parameter can be one of these: -m(mount) OR -u(umount)"
    echo "2'nd parameter is the full path of rootfs directory(with trailing '/')"
    echo ""
    echo "For example: ch-mount -m /media/sdcard/"
    echo ""
    echo 1st parameter : ${1}
    echo 2nd parameter : ${2}
fi

Obdivujeme dosiahnutý výsledok:

$ .\/ch-mount.sh -m rootfs\/\n# cat \/etc\/os-release\nNAME="Ubuntu"\nVERSION="20.04 LTS (Focal Fossa)"\nID=ubuntu\nID_LIKE=debian\nPRETTY_NAME="Ubuntu 20.04 LTS"\nVERSION_ID="20.04"\nHOME_URL="https:\/\/www.ubuntu.com\/"\nSUPPORT_URL="https:\/\/help.ubuntu.com\/"\nBUG_REPORT_URL="https:\/\/bugs.launchpad.net\/ubuntu\/"\nPRIVACY_POLICY_URL="https:\/\/www.ubuntu.com\/legal\/terms-and-policies\/privacy-policy"\nVERSION_CODENAME=focal\nUBUNTU_CODENAME=focal\n# uname -a\nLinux NShubin 5.5.9-gentoo-x86_64 #1 SMP PREEMPT Mon Mar 16 14:34:52 MSK 2020 armv7l armv7l armv7l GNU\/Linux

Pre zaujímavosť zmerajme veľkosť pred a po inštalácii minimálneho (pre mňa) súboru balíkov:

# du -d 0 -h / 2>/dev/null
63M     /

Aktualizujeme:

# apt update
# apt upgrade --yes

Nainštalujeme nasledujúce balíky:

# SYSTEMD_IGNORE_CHROOT=yes apt install --yes autoconf kmod socat ifupdown ethtool iputils-ping net-tools ssh g++ iproute2 dhcpcd5 incron ser2net udev systemd gcc minicom vim cmake make mtd-utils util-linux git strace gdb libiio-dev iiod

Hlavičkové súbory jadra, moduly, to je samostatná téma. Zavadzač, jadro, moduly, zariadenie cez Ubuntu samozrejme nenainštalujeme. Prídu k nám zvonku alebo si ich sami zostavíme alebo nám ich poskytne výrobca dosky, v každom prípade je to mimo tohto návodu.

Do určitej miery je rozdiel v verziách prípustný, ale lepšie je získať ich zo zostavenia jadra.

# apt install --yes linux-headers-generic

Pozrieme sa, čo sa podarilo, a podarilo sa toho dosť:

# apt clean
# du -d 0 -h / 2>/dev/null
770M    /

Nezabudnite nastaviť heslo.

Balič obraz

$ sudo tar -C rootfs --transform "s|^.\/||" --numeric-owner --owner=0 --group=0 -c .\/ | tar --delete .\/ | gzip > rootfs.tar.gz

Okrem toho môžeme nainštalovať etckeeper s nastavením autopush

Predpokladajme, že sme rozdali našu zostavu, práca začala, ako najlepšie zostaviť rôzne verzie našej sústavy neskôr.

Na pomoc nám môže prísť etckeeper.

Bezpečnosť je osobná záležitosť každého:

  • môžete chrániť určité vetvy
  • generovať unikátne kľúče pre každé zariadenie
  • zakázať force push
  • a pod.
# ssh-keygen
# apt install etckeeper
# etckeeper init
# cd /etc
# git remote add origin ...

Nastavíme autopush

Samozrejme, môžeme vopred vytvoriť vetvy na zariadení (napríklad urobiť skript alebo službu, ktorá sa spustí pri prvom spustení).

# cat /etc/etckeeper/etckeeper.conf
PUSH_REMOTE="origin"

Ale môžeme to spraviť aj prefíkane...

Lenivá cesta

Nech máme nejaké unikátne identifikátor, povedzme sériové číslo procesora (alebo MAC — seriózne firmy nakupujú rozmedzie):

cat \/proc\/cpuinfo

# cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 5 (v7l)
BogoMIPS        : 60.36
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc07
CPU revision    : 5

processor       : 1
model name      : ARMv7 Processor rev 5 (v7l)
BogoMIPS        : 60.36
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc07
CPU revision    : 5

Hardware        : Freescale i.MX7 Dual (Device Tree)
Revision        : 0000
Serial          : 06372509

Potom ho môžeme použiť ako názov vetvy, do ktorej budeme pushovať:

# cat /proc/cpuinfo | grep Serial | cut -d':' -f 2 | tr -d [:blank:]
06372509

Vytvorme jednoduchý skript:

# cat /etc/etckeeper/commit.d/40myown-push
#!/bin/sh
set -e

if [ "$VCS" = git ] && [ -d .git ]; then
  branch=$(cat /proc/cpuinfo | grep Serial | cut -d':' -f 2 | tr -d [:blank:])
  cd /etc/
  git push origin master:${branch}
fi

A všetko — po určitom čase si môžeme pozrieť zmeny a vytvoriť zoznam balíkov pre cieľový firmware.

Odporúčané materiály

BINFMT_MISC
Podpora jadra pre rozličné binárne formáty (binfmt_misc)
Kompilácia s qemu user chroot
Budovanie Ubuntu rootfs pre ARM
Ako vytvoriť vlastný Ubuntu live od základov
Crossdev qemu-static-user-chroot
etckeeper

problém getdents64

readdir() vracia NULL (errno=EOVERFLOW) pre 32-bitový user-static qemu na 64-bitovom hostiteľovi
Ext4 64 bit hash spôsobuje problémy s 32 bitovým glibc 2.28+
compiler_id_detection zlyháva pre armhf pri používaní QEMU emulácie v užívateľskom režime
CMake nefunguje správne pod qemu-arm

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster