Создавање слика на Ubuntu за ARM „од нула“

Кога развојот штотуку започнува, често не е јасно кои пакети ќе одат до целните rootfs.

Со други зборови, прерано е да се зграпчите LFS, buildroot или yocto (или нешто друго), но веќе треба да започнете. За богатите (имам 4 GB eMMC на пилот примероци) постои излез да им се дистрибуира на програмерите дистрибуција што ќе им овозможи брзо да испорачаат нешто што моментално недостасува, а потоа секогаш можеме да собираме списоци со пакети и да креираме листа за целните rootfs.

Оваа статија не е нова и е едноставна инструкција за копирање-пејст.

Целта на статијата е да се изградат Ubuntu rootfs за ARM табли (во мојот случај, базирани на Colibri imx7d).

Градење слика

Ние ги собираме целните rootf за репликација.

Отпакување на базата на Ubuntu

Ние сами го избираме изданието врз основа на потребата и нашите сопствени преференции. Еве јас дадов 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

Проверка на поддршката за BINFMT во кернелот

Ако имате заедничка дистрибуција, тогаш има поддршка за BINFMT_MISC и сè е конфигурирано, ако не, тогаш сигурен сум дека знаете како да овозможите поддршка за BINFMT во кернелот.

Проверете дали BINFMT_MISC е овозможен во кернелот:

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

Сега треба да ги проверите поставките:

$ 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

Можете да се регистрирате рачно користејќи, на пример, еве ги овие упатства.

Поставување статичка рака

Сега ни треба статички склопен примерок qemu.

!!! ВНИМАНИЕ!!!
Ако планирате да користите контејнер за да изградите нешто, проверете:
https://sourceware.org/bugzilla/show_bug.cgi?id=23960
https://bugs.launchpad.net/qemu/+bug/1805913
Потоа, за х86_64 домаќин и гостин за рака, треба да ја користите верзијата 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

Едноставна скрипта:

ch-приклучок.ш

#!/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

Се восхитуваме на резултатот:

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

Само за забава, ајде да ја измериме големината пред и по инсталирањето на минималниот (за мене) сет на пакети:

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

Ајде да се ажурираме:

# apt update
# apt upgrade --yes

Ајде да ги инсталираме пакетите за кои сме заинтересирани:

# 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

Датотеките и модулите со заглавие на јадрото се посебна работа. Се разбира, нема да го инсталираме подигнувачот, кернелот, модулите, дрвото на уредите преку Ubuntu. Ќе ни дојдат однадвор или сами ќе ги составиме или ќе ни ги даде производителот на таблата, во секој случај тоа е надвор од опсегот на ова упатство.

До одреден степен, дивергенцијата на верзијата е прифатлива, но подобро е да ги земете од изградбата на кернелот.

# apt install --yes linux-headers-generic

Ајде да видиме што се случи и испадна многу:

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

Не заборавајте да поставите лозинка.

Пакување на сликата

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

Дополнително, можеме да инсталираме etckeeper со поставката за автоматско притиснување

Па, да речеме дека го дистрибуиравме нашето склопување, започна работата за тоа како најдобро да се склопат подоцна различни верзии на нашиот систем.

итн. чувар може да ни дојде на помош.

Безбедноста е лична работа:

  • можете да заштитите одредени гранки
  • генерира единствен клуч за секој уред
  • оневозможи принудно притискање
  • итн. ...
# ssh-keygen
# apt install etckeeper
# etckeeper init
# cd /etc
# git remote add origin ...

Ајде да поставиме автоматско притискање

Можеме, се разбира, однапред да креираме гранки на уредот (да речеме дека направивме скрипта или услуга што ќе работи првиот пат кога ќе се стартува).

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

Или можеме да направиме нешто попаметно...

Мрзлив начин

Дозволете ни да имаме некој вид уникатен идентификатор, да речеме серискиот број на процесорот (или MAC - сериозни компании го купуваат опсегот):

мачка / 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

Потоа можеме да го користиме за името на гранката до која ќе притиснеме:

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

Ајде да создадеме едноставна скрипта:

# 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

И тоа е сè - по некое време можеме да ги погледнеме промените и да создадеме листа на пакети за целниот фирмвер.

Препорачани материјали

BINFMT_MISC
Поддршка на кернелот за разни бинарни формати (binfmt_misc)
Компилирање со qemu корисник chroot
Градење Ubuntu rootfs за ARM
Како да креирате сопствен Ubuntu во живо од нула
Crossdev qemu-static-user-chroot
итн чувар

getdents64 проблем

readdir() враќа NULL (errno=EOVERFLOW) за 32-битен кориснички статичен qemu на 64-битен домаќин
Ext4 64-битен хаш прекинува 32-битен glibc 2.28+
compiler_id_detection не успева за armhf кога се користи QEMU емулација на кориснички режим
CMake не работи правилно под qemu-arm

Извор: www.habr.com