Ustvarjanje slike Ubuntu za ARM "iz nič"

Ko se razvoj šele začne, pogosto ni jasno, kateri paketi bodo šli v ciljni rootfs.

Z drugimi besedami, prezgodaj je zagrabiti LFS, buildroot ali yocto (ali kaj drugega), vendar morate že začeti. Za bogate (v pilotnih vzorcih imam 4 GB eMMC) obstaja izhod, da razvijalcem razdelimo distribucijo, ki jim bo omogočila hitro dostavo nečesa, kar trenutno manjka, nato pa lahko vedno zberemo sezname paketov in ustvarimo seznam za ciljni rootfs.

Ta članek ni nov in je preprosta navodila za kopiranje in lepljenje.

Namen članka je zgraditi Ubuntu rootfs za plošče ARM (v mojem primeru na podlagi Colibri imx7d).

Grajenje podobe

Sestavimo ciljne rootfs za replikacijo.

Razpakiranje Ubuntu Base

Izpust izberemo sami glede na potrebe in lastne želje. Tukaj sem dal 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

Preverjanje podpore za BINFMT v jedru

Če imate skupno distribucijo, potem obstaja podpora za BINFMT_MISC in je vse konfigurirano, če ne, potem sem prepričan, da veste, kako omogočiti podporo za BINFMT v jedru.

Prepričajte se, da je BINFMT_MISC omogočen v jedru:

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

Zdaj morate preveriti nastavitve:

$ 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

Registrirate se lahko ročno z npr. tukaj so ta navodila.

Nastavitev statične roke qemu

Zdaj potrebujemo statično sestavljen primerek qemu.

!!! POZOR!!!
Če nameravate uporabiti vsebnik za izdelavo nečesa, si oglejte:
https://sourceware.org/bugzilla/show_bug.cgi?id=23960
https://bugs.launchpad.net/qemu/+bug/1805913
Potem morate za gostitelja x86_64 in arm gosta uporabiti različico i386 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
# путь в rootfs и имя исполняемого файла должно совпадать с /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), statically linked, BuildID[sha1]=be45f9a321cccc5c139cc1991a4042907f9673b6, for GNU/Linux 3.2.0, stripped
$ 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), statically linked, BuildID[sha1]=be45f9a321cccc5c139cc1991a4042907f9673b6, for GNU/Linux 3.2.0, stripped

chroot

Preprost skript:

ch-mount.sh

#!/bin/bash

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

function umnt() {
    echo "UNMOUNTING"
    sudo umount proc
    sudo umount sys
    sudo umount dev/pts
    sudo umount 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 : 
    echo 2nd parameter : 
fi

Občudujemo rezultat:

$ ./ch-mount.sh -m rootfs/
# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
# uname -a
Linux NShubin 5.5.9-gentoo-x86_64 #1 SMP PREEMPT Mon Mar 16 14:34:52 MSK 2020 armv7l armv7l armv7l GNU/Linux

Samo za zabavo izmerimo velikost pred in po namestitvi najmanjšega (zame) nabora paketov:

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

Posodobimo:

# apt update
# apt upgrade --yes

Namestimo pakete, ki nas zanimajo:

# 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

Datoteke glave jedra in moduli so ločena zadeva. Seveda ne bomo namestili zagonskega nalagalnika, jedra, modulov, drevesa naprav prek Ubuntuja. K nam bodo prišle od zunaj ali pa jih bomo sestavili sami ali pa nam jih bo dal proizvajalec plošč, v vsakem primeru pa to presega obseg tega navodila.

Do neke mere so razlike v različicah sprejemljive, vendar jih je bolje vzeti iz gradnje jedra.

# apt install --yes linux-headers-generic

Poglejmo, kaj se je zgodilo in izkazalo se je veliko:

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

Ne pozabite nastaviti gesla.

Pakiranje slike

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

Poleg tega lahko namestimo etckeeper z nastavitvijo autopush

No, recimo, da smo razdelili naš sklop, začelo se je delo na tem, kako najbolje sestaviti pozneje različne različice našega sistema.

etckeeper nam lahko priskoči na pomoč.

Varnost je osebna stvar:

  • lahko zaščitite določene veje
  • ustvarite edinstven ključ za vsako napravo
  • onemogočite prisilni pritisk
  • itd. ...
# ssh-keygen
# apt install etckeeper
# etckeeper init
# cd /etc
# git remote add origin ...

Nastavimo autopush

Seveda lahko vnaprej ustvarimo veje na napravi (recimo naredimo skripto ali storitev, ki bo delovala ob prvem zagonu).

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

Lahko pa naredimo kaj pametnejšega...

Leni način

Imejmo nekakšen edinstven identifikator, recimo serijsko številko procesorja (ali MAC - resna podjetja kupujejo ponudbo):

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

Nato ga lahko uporabimo za ime veje, v katero bomo potisnili:

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

Ustvarimo preprost 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

In to je vse - čez nekaj časa si lahko ogledamo spremembe in ustvarimo seznam paketov za ciljno vdelano programsko opremo.

Priporočeni materiali

BINFMT_MISC
Podpora jedra za različne binarne formate (binfmt_misc)
Prevajanje z uporabnikom qemu chroot
Gradnja Ubuntu rootfs za ARM
Kako ustvariti Ubuntu po meri v živo iz nič
Crossdev qemu-static-user-chroot
etckeeper

težava getdents64

readdir() vrne NULL (errno=EOVERFLOW) za 32-bitni uporabniško statični qemu na 64-bitnem gostitelju
Ext4 64-bitno zgoščevanje prekine 32-bitni glibc 2.28+
compiler_id_detection ne uspe za armhf pri uporabi emulacije uporabniškega načina QEMU
CMake ne deluje pravilno pod qemu-arm

Vir: www.habr.com