Creating an Ubuntu image for ARM 'from scratch'

Wanneer de ontwikkeling net begint, is het vaak nog onduidelijk welke pakketten naar de doel-rootfs zullen gaan.

Met andere woorden, het is te vroeg om te grijpen naar LFS, buildroot of yocto (of iets anders), maar we moeten al wel beginnen. Voor degenen met voldoende middelen (ik heb op mijn pilotsamples 4GB eMMC) is er een oplossing: geef de ontwikkelaars een distributie die hen in staat stelt om snel iets te leveren dat momenteel ontbreekt, en daarna kunnen we altijd opnieuw lijsten van pakketten samenstellen en een lijst voor de doel-rootfs maken.

Dit artikel bevat geen nieuwigheden en is in wezen een eenvoudige copy-paste instructie.

Het doel van het artikel is de bouw van Ubuntu rootfs voor ARM borden (in mijn geval op basis van Colibri imx7d).

Bouwen van de afbeelding

Laten we de doel-rootfs samenstellen voor distributie.

Pak Ubuntu Base uit

Kies de release op basis van behoeften en persoonlijke voorkeuren. Hier heb ik 20 gegeven.

$ 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

Controleer ondersteuning voor BINFMT in de kernel

Als je een gangbare distributie hebt, is de ondersteuning voor BINFMT_MISC aanwezig en is alles ingesteld; als dat niet het geval is, weet je waarschijnlijk hoe je BINFMT-ondersteuning in de kernel moet inschakelen.

Zorg ervoor dat BINFMT_MISC is ingeschakeld in de kernel:

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

Nu moeten we de instellingen controleren:

$ 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

Je kunt handmatig registreren met behulp van bijvoorbeeld deze instructie.

Instelling van qemu static arm

Nu hebben we een versie van qemu nodig die statisch is samengesteld.

!!! LET OP!!!
Als je van plan bent om een container te gebruiken voor het bouwen van iets, bekijk dan:
https://sourceware.org/bugzilla/show_bug.cgi?id=23960
https://bugs.launchpad.net/qemu/+bug/1805913
Daarom moet je voor een x86_64-host en arm-guest de i386-versie van qemu gebruiken:
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
# Het pad in rootfs en de naam van het uitvoerbare bestand moeten overeenkomen met /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), statisch gelinkt, BuildID[sha1]=be45f9a321cccc5c139cc1991a4042907f9673b6, voor GNU/Linux 3.2.0, gestript
$ 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), statisch gelinkt, BuildID[sha1]=be45f9a321cccc5c139cc1991a4042907f9673b6, voor GNU/Linux 3.2.0, gestript

Chroot

Eenvoudig script:

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

Laten we genieten van het verkregen resultaat:

$ .\/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

Laten we uit nieuwsgierigheid de grootte voor en na de installatie van de minimale (voor mij) set pakketten meten:

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

Laten we updaten:

# apt update
# apt upgrade --yes

Laten we de pakketten installeren die we willen:

# 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

De headerbestanden van de kernel, modules, dat is een apart verhaal. We kunnen de bootloader, kernel, modules, device tree natuurlijk niet via Ubuntu installeren. Ze zullen van buitenaf komen, of we verzamelen ze zelf, of de fabrikant van het bord levert ze ons, hoe dan ook, dit valt buiten deze instructie.

Tot op zekere hoogte is een versieverschil toegestaan, maar het is beter om ze van de kernelbuild te nemen.

# apt install --yes linux-headers-generic

Laten we kijken wat we hebben en dat is behoorlijk wat:

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

Vergeet niet een wachtwoord in te stellen.

Laten we de schijfbundel maken

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

We kunnen ook etckeeper installeren met de configuratie autopush

Stel dat we onze build verspreid hebben, het werk is begonnen, hoe kunnen we later verschillende versies van ons systeem het beste samenstellen.

Etckeeper kan ons hierbij helpen.

Veiligheid is een persoonlijke zaak:

  • je kunt bepaalde takken beschermen
  • een unieke sleutel voor elk apparaat genereren
  • force push verbieden
  • enzovoort ...
# ssh-keygen
# apt install etckeeper
# etckeeper init
# cd /etc
# git remote add origin ...

Laten we autopush configureren

We kunnen natuurlijk van tevoren takken op het apparaat maken (bijvoorbeeld een script of service maken die wordt uitgevoerd bij de eerste opstart).

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

Of we kunnen het slimmer aanpakken...

De luie weg

Laten we zeggen dat we een unieke identifier hebben, bijvoorbeeld het serienummer van de processor (of MAC - serieuze bedrijven kopen een bereik):

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

Dan kunnen we deze gebruiken als de naam van de tak waarop we gaan pushen:

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

Laten we een eenvoudig script maken:

# 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

En dat is het - na een tijdje kunnen we de wijzigingen bekijken en een lijst van pakketten voor de doelfirmware opstellen.

Aanbevolen materialen

BINFMT_MISC
Kernelondersteuning voor verschillende binaire indelingen (binfmt_misc)
Compileren met qemu user chroot
Ubuntu rootfs bouwen voor ARM
Hoe een aangepaste Ubuntu live vanaf nul te creƫren
Crossdev qemu-static-user-chroot
etckeeper

probleem getdents64

readdir() retourneert NULL (errno=EOVERFLOW) voor 32-bits user-static qemu op 64-bits host
Ext4 64 bit hash breekt 32 bit glibc 2.28+
compiler_id_detection heeft problemen voor armhf bij gebruik van QEMU user-mode emulation
CMake werkt niet goed onder qemu-arm

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers šŸ”„ Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster