Tạo hình ảnh Ubuntu cho ARM "từ đầu"

Khi quá trình phát triển mới bắt đầu, thường không rõ gói nào sẽ đi tới rootf mục tiêu.

Nói cách khác, còn quá sớm để lấy LFS, buildroot hoặc yocto (hoặc thứ gì khác), nhưng bạn đã cần phải bắt đầu. Đối với người giàu (tôi có 4GB eMMC trên các mẫu thử nghiệm), có một cách để phân phối cho các nhà phát triển một bản phân phối cho phép họ nhanh chóng phân phối thứ hiện đang bị thiếu và sau đó chúng tôi luôn có thể thu thập danh sách các gói và tạo danh sách cho các rootf mục tiêu.

Bài viết này không mới và chỉ là một hướng dẫn sao chép-dán đơn giản.

Mục đích của bài viết là xây dựng Ubuntu rootfs cho bo mạch ARM (trong trường hợp của tôi là dựa trên Colibri imx7d).

Xây dựng hình ảnh

Chúng tôi tập hợp các rootf mục tiêu để nhân rộng.

Giải nén cơ sở Ubuntu

Chúng tôi tự chọn bản phát hành dựa trên nhu cầu và sở thích của riêng mình. Ở đây tôi đã đưa ra 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

Kiểm tra hỗ trợ BINFMT trong kernel

Nếu bạn có bản phân phối chung thì có hỗ trợ BINFMT_MISC và mọi thứ đều được định cấu hình, nếu không, thì tôi chắc chắn rằng bạn biết cách bật hỗ trợ BINFMT trong kernel.

Đảm bảo BINFMT_MISC được bật trong kernel:

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

Bây giờ bạn cần kiểm tra cài đặt:

$ 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

Bạn có thể đăng ký thủ công bằng cách sử dụng, ví dụ: đây là những hướng dẫn này.

Thiết lập cánh tay tĩnh qemu

Bây giờ chúng ta cần một phiên bản qemu được lắp ráp tĩnh.

!!! CHÚ Ý!!!
Nếu bạn dự định sử dụng vùng chứa để xây dựng thứ gì đó, hãy xem:
https://sourceware.org/bugzilla/show_bug.cgi?id=23960
https://bugs.launchpad.net/qemu/+bug/1805913
Sau đó, đối với máy chủ x86_64 và máy khách, bạn cần sử dụng phiên bản qemu i386:
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

Kịch bản đơn giản:

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úng tôi ngưỡng mộ kết quả:

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

Để giải trí, hãy đo kích thước trước và sau khi cài đặt bộ gói tối thiểu (đối với tôi):

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

Hãy cập nhật:

# apt update
# apt upgrade --yes

Hãy cài đặt các gói mà chúng tôi quan tâm:

# 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

Các tệp và mô-đun tiêu đề hạt nhân là một vấn đề riêng biệt. Tất nhiên, chúng tôi sẽ không cài đặt bootloader, kernel, mô-đun, cây thiết bị qua Ubuntu. Chúng sẽ đến với chúng tôi từ bên ngoài hoặc chúng tôi sẽ tự lắp ráp chúng hoặc chúng sẽ được nhà sản xuất bo mạch cung cấp cho chúng tôi, trong mọi trường hợp, điều này nằm ngoài phạm vi của hướng dẫn này.

Ở một mức độ nào đó, sự phân kỳ phiên bản có thể chấp nhận được, nhưng tốt hơn là nên lấy chúng từ bản dựng kernel.

# apt install --yes linux-headers-generic

Hãy xem điều gì đã xảy ra và nó diễn ra rất nhiều:

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

Đừng quên đặt mật khẩu.

Đóng gói hình ảnh

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

Ngoài ra, chúng ta có thể cài đặt etckeeper bằng cài đặt autopush

Chà, giả sử chúng tôi đã phân phối bản lắp ráp của mình, công việc bắt đầu tìm cách tốt nhất để lắp ráp các phiên bản khác nhau sau này của hệ thống của chúng tôi.

etckeeper có thể hỗ trợ chúng tôi.

An toàn là vấn đề cá nhân:

  • bạn có thể bảo vệ một số nhánh nhất định
  • tạo một khóa duy nhất cho mỗi thiết bị
  • vô hiệu hóa lực đẩy
  • vân vân. ...
# ssh-keygen
# apt install etckeeper
# etckeeper init
# cd /etc
# git remote add origin ...

Hãy thiết lập autopush

Tất nhiên, chúng tôi có thể tạo trước các nhánh trên thiết bị (giả sử chúng tôi tạo một tập lệnh hoặc dịch vụ sẽ chạy trong lần khởi chạy đầu tiên).

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

Hoặc chúng ta có thể làm điều gì đó thông minh hơn...

Cách lười biếng

Hãy để chúng tôi có một số loại mã định danh duy nhất, giả sử số sê-ri của bộ xử lý (hoặc MAC - các công ty nghiêm túc mua phạm vi):

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

Sau đó, chúng ta có thể sử dụng nó cho tên của nhánh mà chúng ta sẽ đẩy tới:

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

Hãy tạo một tập lệnh đơn giản:

# 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

Và chỉ vậy thôi - sau một thời gian, chúng ta có thể xem xét các thay đổi và tạo danh sách các gói cho phần sụn đích.

Vật liệu được đề xuất

BINFMT_MISC
Hỗ trợ hạt nhân cho các định dạng nhị phân khác (binfmt_misc)
Biên dịch với chroot người dùng qemu
Xây dựng rootf Ubuntu cho ARM
Cách tạo Ubuntu tùy chỉnh trực tiếp từ đầu
Crossdev qemu-static-user-chroot
thợ khắc

vấn đề getdents64

readdir() trả về NULL (errno=EOVERFLOW) cho qemu tĩnh người dùng 32 bit trên máy chủ 64 bit
Băm Ext4 64 bit phá vỡ glibc 32 bit 2.28+
trình biên dịch_id_ detect không thành công cho armhf khi sử dụng mô phỏng chế độ người dùng QEMU
CMake không hoạt động bình thường dưới qemu-arm

Nguồn: www.habr.com