“從頭開始”為 ARM 構建 Ubuntu 映像

當開發剛剛開始時,通常還不清楚哪些包將進入目標 rootfs。

換句話說,現在掌握 LFS、buildroot 或 yocto(或其他東西)還為時過早,但您已經需要開始了。 對於富人來說(我的試點樣品有 4GB eMMC),有一種方法可以向開發人員分發分發套件,使他們能夠快速交付目前缺少的東西,然後我們可以隨時收集軟件包列表並形成一個目標rootfs 的列表。

這篇文章並不新鮮,只是簡單的複制粘貼說明。

本文的目的是為 ARM 板構建 Ubuntu rootfs(在我的例子中基於 Colibri imx7d)。

構建圖像

我們收集目標 rootfs 進行複制。

解壓 Ubuntu Base

我們根據需要和自己的喜好自行選擇版本。 這裡我給了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主機和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

內核頭文件、模塊,這是一個單獨的話題。 當然,我們不會通過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

此外,我們可以使用 autopush 設置安裝 etckeeper

好吧,假設我們分發了我們的程序集,工作繼續進行,如何最好地組裝我們系統的各個版本。

etckeeper 可以為我們提供幫助。

安全是每個人的事:

  • 你可以保護某些分支
  • 為每個設備生成唯一的密鑰
  • 禁用強制推送
  • ETC。 ……
# 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 進行編譯
為 ARM 構建 Ubuntu rootfs
如何從頭開始創建自定義 Ubuntu
crossdev qemu-靜態-用戶-chroot
等等管理員

getdents64 問題

對於 32 位主機上的 64 位用戶靜態 qemu,readdir() 返回 NULL (errno=EOVERFLOW)
Ext4 64 位哈希破壞 32 位 glibc 2.28+
使用 QEMU 用戶模式仿真時,armhf 的compiler_id_detection 失敗
CMake 在 qemu-arm 下無法正常工作

來源: www.habr.com