ایجاد یک تصویر اوبونتو برای ARM "از ابتدا"

هنگامی که توسعه تازه شروع می شود، اغلب مشخص نیست که کدام بسته ها به rootfs هدف می روند.

به عبارت دیگر، برای گرفتن LFS، buildroot یا yocto (یا چیز دیگری) خیلی زود است، اما از قبل باید شروع کنید. برای ثروتمندان (من 4 گیگابایت eMMC در نمونه های آزمایشی دارم) راهی برای توزیع بین توسعه دهندگان وجود دارد که به آنها امکان می دهد به سرعت چیزی را که در حال حاضر گم شده است تحویل دهند، و سپس ما همیشه می توانیم لیست بسته ها را جمع آوری کنیم و لیستی برای آنها ایجاد کنیم. ریشه های هدف

این مقاله جدید نیست و یک دستورالعمل کپی پیست ساده است.

هدف مقاله ساخت rootfهای اوبونتو برای بردهای ARM است (در مورد من، بر اساس Colibri imx7d).

تصویر را بسازید

ما ریشه های هدف را برای تکثیر جمع می کنیم.

باز کردن پایه اوبونتو

ما خودمان نسخه را بر اساس نیاز و ترجیحات خود انتخاب می کنیم. اینجا من 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

اکنون به یک نمونه qemu مونتاژ شده نیاز داریم.

!!! توجه!!!
اگر قصد دارید از یک ظرف برای ساختن چیزی استفاده کنید، بررسی کنید:
https://sourceware.org/bugzilla/show_bug.cgi?id=23960
https://bugs.launchpad.net/qemu/+bug/1805913
سپس برای x86_64 host و arm guest باید از نسخه 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

کروت

اسکریپت ساده:

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

ما نتیجه را تحسین می کنیم:

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

فایل‌های هدر هسته و ماژول‌ها موضوعی جداگانه هستند. البته بوت لودر، کرنل، ماژول ها، درخت دستگاه را از طریق اوبونتو نصب نمی کنیم. آنها از خارج به ما مراجعه می کنند یا خودمان آنها را مونتاژ می کنیم یا توسط سازنده برد در اختیار ما قرار می گیرد، در هر صورت این موضوع از حوصله این دستورالعمل خارج است.

تا حدودی، واگرایی نسخه قابل قبول است، اما بهتر است آنها را از بیلد کرنل بگیرید.

# 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 را با تنظیمات autopush نصب کنیم

خوب، فرض کنید ما مونتاژ خود را توزیع کردیم، کار بر روی بهترین روش برای مونتاژ نسخه های بعدی سیستم ما آغاز شد.

نگهبان غیره می تواند به کمک ما بیاید.

ایمنی یک موضوع شخصی است:

  • شما می توانید از شاخه های خاصی محافظت کنید
  • برای هر دستگاه یک کلید منحصر به فرد ایجاد کنید
  • فشار نیرو را غیرفعال کنید
  • و غیره. ...
# ssh-keygen
# apt install etckeeper
# etckeeper init
# cd /etc
# git remote add origin ...

بیایید فشار خودکار را تنظیم کنیم

البته می‌توانیم از قبل شعبه‌هایی روی دستگاه ایجاد کنیم (مثلاً یک اسکریپت یا سرویسی می‌سازیم که اولین باری که راه‌اندازی می‌شود اجرا می‌شود).

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

یا می توانیم کاری هوشمندانه تر انجام دهیم...

راه تنبلی

اجازه دهید یک نوع شناسه منحصر به فرد داشته باشیم، مثلاً شماره سریال پردازنده (یا MAC - شرکت های جدی محدوده را خریداری می کنند):

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

سپس می توانیم از آن برای نام شاخه ای که به آن فشار می دهیم استفاده کنیم:

# 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
ساخت rootfs اوبونتو برای ARM
چگونه از ابتدا یک Ubuntu Live سفارشی ایجاد کنیم
Crossdev qemu-static-user-chroot
نگهبان غیره

مشکل getdents64

readdir() NULL (errno=EOVERFLOW) را برای qemu کاربر استاتیک 32 بیتی در میزبان 64 بیتی برمی گرداند.
Ext4 هش 64 بیتی 32 بیت glibc 2.28+ را می شکند
هنگام استفاده از شبیه‌سازی حالت کاربر QEMU، compiler_id_detection برای armhf ناموفق است
CMake در qemu-arm به درستی کار نمی کند

منبع: www.habr.com