当开发刚刚开始时,通常不清楚哪些包将进入目标 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
chroot环境
简单的脚本:
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 - 严肃的公司购买该系列):
猫/ 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
就这样 - 一段时间后,我们可以查看更改并为目标固件创建软件包列表。
推荐材料
getdents64 问题
来源: habr.com