Arch Linux 在红米5 Plus (MSM8953) 上的移植

2024-02-13

前言

在 Android 上运行 Linux 发行版这件事我大概从 18 年就开始了,但是当时是使用 termux+proot 的组合,后面写了个脚本来调用 unshare,使用 magisk 来随系统启动,一直到现在hhh

前些天收拾东西发现有个被遗忘的红米 5 PLus,但是无限重启,在下载固件时发现 Vince 有 postmarkedOS 的支持,故事从此开始~

pmOS 是一个基于 Alpine 的发行版,Alpine 是个使用musl 和openrc 而非 glibc+systemd 的 Linux 发行版,但这问题不大本人日常用 Void Linux 也是 musl+runit 的组合,但是把 Alpine 用在容器以外的地方还是感觉有的怪(x,还是用 Arch Linux 比较

好了,开始正文部分

要在手机上跑起来 Linux 发行版(说起来 Android 被开除 Linux 籍了)首先要准备一个 bootloader,其次是一个 Linux Kernel,最后再来一个 rootfs 就好了

bootloader 目前可用的有 lk2nd 和 edk2(SDM835以上),Vince 是 sd625,选 lk2nd。我这里直接用 pmOS 编译好的 lk2nd 镜像,下面就开始内核以及 rootfs 的准备

环境准备

我这里使用了 Debian12 (AMD64) 来进行交叉编译,有条件可以直接使用 ARM64 的设备(比如手机或者 ARM 的主机/服务器)来编译

安装依赖

交叉编译环境:

1sudo apt install build-essential openssl pkg-config libssl-dev libncurses5-dev pkg-config minizip libelf-dev flex bison  libc6-dev libidn11-dev rsync bc liblz4-tool  
2sudo apt install gcc-aarch64-linux-gnu dpkg dpkg-dev git debhelper

rootfs 构建:

1sudo apt install arch-install-scripts qemu-user-static  android-platform-system-core mkbootimg

内核构建

内核源码: https://github.com/msm8953-mainline/linux

config: postmarketOS/pmaports

如果使用 Archlinux 也可以用 makepkg 构建,PKGBUILD 如下:

  1# AArch64 MSM8953
  2# Maintainer: Zmyeir <[email protected]>
  3
  4buildarch=8
  5
  6pkgbase=linux-aarch64
  7pkgver=6.7.2
  8pkgrel=1
  9_kernelname=${pkgbase#linux}
 10_desc="AArch64 qcom msm8953"
 11_srcdir=linux-${pkgver}-r0
 12arch=('aarch64')
 13url="https://github.com/msm8953-mainline/linux"
 14license=('GPL2')
 15makedepends=('bc' 'dtc' 'kmod' 'inetutils' 'git' 'tar' 'xz' 'xmlto')
 16options=('!strip')
 17source=("https://github.com/msm8953-mainline/linux/archive/refs/tags/v${pkgver}-r0.tar.gz"
 18        'config'
 19)
 20sha256sums=('SKIP'
 21            'SKIP')
 22
 23prepare() {
 24  cd $_srcdir
 25
 26  echo "Setting version..."
 27  #scripts/setlocalversion --save-scmversion
 28  echo "-$pkgrel" > localversion.10-pkgrel
 29  echo "${pkgbase#linux}" > localversion.20-pkgname
 30  cat "${srcdir}/config" > ./.config
 31}
 32
 33build() {
 34  cd ${_srcdir}
 35
 36  # get kernel version
 37  make prepare
 38  make -s kernelrelease > version
 39
 40  # build!
 41  unset LDFLAGS
 42  make ${MAKEFLAGS} Image Image.gz modules
 43  # Generate device tree blobs with symbols to support applying device tree overlays in U-Boot
 44  make ${MAKEFLAGS} DTC_FLAGS="-@" dtbs
 45}
 46
 47_package() {
 48  pkgdesc="The Linux Kernel and modules - ${_desc}"
 49  depends=('coreutils' 'initramfs' 'kmod' 'mkinitcpio>=0.7')
 50  optdepends=('wireless-regdb: to set the correct wireless channels of your country'
 51              'linux-firmware: firmware images needed for some devices')
 52  provides=("linux=${pkgver}" "WIREGUARD-MODULE")
 53  conflicts=('linux')
 54
 55  cd $_srcdir
 56  local kernver="$(<version)"
 57  local modulesdir="$pkgdir/usr/lib/modules/$kernver"
 58
 59  echo "Installing boot image and dtbs..."
 60  install -Dm644 arch/arm64/boot/Image{,.gz} -t "${pkgdir}/boot"
 61  install -Dt "$modulesdir/dtbs" arch/arm64/boot/dts/qcom/msm8953*.dtb
 62 
 63  # Used by mkinitcpio to name the kernel
 64  echo "$pkgbase" | install -Dm644 /dev/stdin "$modulesdir/pkgbase"
 65
 66  echo "Installing modules..."
 67  make INSTALL_MOD_PATH="$pkgdir/usr" INSTALL_MOD_STRIP=1 modules_install
 68
 69  # remove build and source links
 70  rm "$modulesdir"/{source,build} || true
 71
 72}
 73
 74_package-headers() {
 75  pkgdesc="Header files and scripts for building modules for linux kernel - ${_desc}"
 76  depends=(pahole)
 77
 78  cd $_srcdir
 79  local builddir="$pkgdir/usr/lib/modules/$(<version)/build"
 80
 81  echo "Installing build files..."
 82  install -Dt "$builddir" -m644 .config Makefile Module.symvers System.map \
 83    localversion.* version vmlinux
 84  install -Dt "$builddir/kernel" -m644 kernel/Makefile
 85  install -Dt "$builddir/arch/arm64" -m644 arch/arm64/Makefile
 86  cp -t "$builddir" -a scripts
 87
 88  echo "Installing headers..."
 89  cp -t "$builddir" -a include
 90  cp -t "$builddir/arch/arm64" -a arch/arm64/include
 91  install -Dt "$builddir/arch/arm64/kernel" -m644 arch/arm64/kernel/asm-offsets.s
 92  mkdir -p "$builddir/arch/arm"
 93  cp -t "$builddir/arch/arm" -a arch/arm/include
 94
 95  install -Dt "$builddir/drivers/md" -m644 drivers/md/*.h
 96  install -Dt "$builddir/net/mac80211" -m644 net/mac80211/*.h
 97
 98  # https://bugs.archlinux.org/task/13146
 99  install -Dt "$builddir/drivers/media/i2c" -m644 drivers/media/i2c/msp3400-driver.h
100
101  # https://bugs.archlinux.org/task/20402
102  install -Dt "$builddir/drivers/media/usb/dvb-usb" -m644 drivers/media/usb/dvb-usb/*.h
103  install -Dt "$builddir/drivers/media/dvb-frontends" -m644 drivers/media/dvb-frontends/*.h
104  install -Dt "$builddir/drivers/media/tuners" -m644 drivers/media/tuners/*.h
105
106  # https://bugs.archlinux.org/task/71392
107  install -Dt "$builddir/drivers/iio/common/hid-sensors" -m644 drivers/iio/common/hid-sensors/*.h
108
109  echo "Installing KConfig files..."
110  find . -name 'Kconfig*' -exec install -Dm644 {} "$builddir/{}" \;
111
112  echo "Removing unneeded architectures..."
113  local arch
114  for arch in "$builddir"/arch/*/; do
115    [[ $arch = */arm64/ || $arch == */arm/ ]] && continue
116    echo "Removing $(basename "$arch")"
117    rm -r "$arch"
118  done
119
120  echo "Removing documentation..."
121  rm -r "$builddir/Documentation"
122
123  echo "Removing broken symlinks..."
124  find -L "$builddir" -type l -printf 'Removing %P\n' -delete
125
126  echo "Removing loose objects..."
127  find "$builddir" -type f -name '*.o' -printf 'Removing %P\n' -delete
128
129  echo "Stripping build tools..."
130  local file
131  while read -rd '' file; do
132    case "$(file -bi "$file")" in
133      application/x-sharedlib\;*)      # Libraries (.so)
134        strip -v $STRIP_SHARED "$file" ;;
135      application/x-archive\;*)        # Libraries (.a)
136        strip -v $STRIP_STATIC "$file" ;;
137      application/x-executable\;*)     # Binaries
138        strip -v $STRIP_BINARIES "$file" ;;
139      application/x-pie-executable\;*) # Relocatable binaries
140        strip -v $STRIP_SHARED "$file" ;;
141    esac
142  done < <(find "$builddir" -type f -perm -u+x ! -name vmlinux -print0)
143
144  echo "Adding symlink..."
145  mkdir -p "$pkgdir/usr/src"
146  ln -sr "$builddir" "$pkgdir/usr/src/$pkgbase"
147}
148
149pkgname=("${pkgbase}" "${pkgbase}-headers")
150for _p in ${pkgname[@]}; do
151  eval "package_${_p}() {
152    _package${_p#${pkgbase}}
153  }"
154done

源码拉取

拉取 v6.7.2-r0 分支(本文发布时最新签出)

1mkdir ~/vince
2cd ~/vince
3git clone https://github.com/msm8953-mainline/linux.git -b v6.7.2-r0 --depth 1
4cd linux

处理 Config

使用@HandsomeHacker的脚本处理 config:

1./check.sh </path/to/file> -w

脚本如下:

  1#!/bin/bash
  2
  3FILE=$1
  4
  5[ -f "$FILE" ] || {
  6	echo "Provide a config file as argument"
  7	exit
  8}
  9
 10write=false
 11
 12if [ "$2" = "-w" ]; then
 13	write=true
 14fi
 15
 16CONFIGS_ON="
 17CONFIG_IKCONFIG
 18CONFIG_CPUSETS
 19CONFIG_AUTOFS4_FS
 20CONFIG_TMPFS_XATTR
 21CONFIG_TMPFS_POSIX_ACL
 22CONFIG_CGROUP_DEVICE
 23CONFIG_CGROUP_MEM_RES_CTLR
 24CONFIG_CGROUP_MEM_RES_CTLR_SWAP
 25CONFIG_CGROUP_MEM_RES_CTLR_KMEM
 26CONFIG_RTC_DRV_CMOS
 27CONFIG_BLK_CGROUP
 28CONFIG_CGROUP_PERF
 29CONFIG_IKCONFIG_PROC
 30CONFIG_SYSVIPC
 31CONFIG_CGROUPS
 32CONFIG_CGROUP_FREEZER
 33CONFIG_NAMESPACES
 34CONFIG_UTS_NS
 35CONFIG_IPC_NS
 36CONFIG_USER_NS
 37CONFIG_PID_NS
 38CONFIG_NET_NS
 39CONFIG_AUDIT
 40CONFIG_AUDITSYSCALL
 41CONFIG_AUDIT_TREE
 42CONFIG_AUDIT_WATCH
 43CONFIG_CC_STACKPROTECTOR
 44CONFIG_DEBUG_RODATA
 45CONFIG_DEVTMPFS
 46CONFIG_DEVTMPFS_MOUNT
 47CONFIG_DEVPTS_MULTIPLE_INSTANCES
 48CONFIG_ECRYPT_FS
 49CONFIG_ECRYPT_FS_MESSAGING
 50CONFIG_ENCRYPTED_KEYS
 51CONFIG_EXT4_FS_POSIX_ACL
 52CONFIG_EXT4_FS_SECURITY
 53CONFIG_FSNOTIFY
 54CONFIG_DNOTIFY
 55CONFIG_INOTIFY_USER
 56CONFIG_FANOTIFY
 57CONFIG_FANOTIFY_ACCESS_PERMISSIONS
 58CONFIG_KEYS
 59CONFIG_SWAP
 60CONFIG_VT
 61CONFIG_VT_CONSOLE
 62CONFIG_SECCOMP
 63CONFIG_STRICT_DEVMEM
 64CONFIG_SYN_COOKIES
 65CONFIG_BT
 66CONFIG_BT_RFCOMM
 67CONFIG_BT_RFCOMM_TTY
 68CONFIG_BT_BNEP
 69CONFIG_BT_BNEP_MC_FILTER
 70CONFIG_BT_BNEP_PROTO_FILTER
 71CONFIG_BT_HIDP
 72CONFIG_XFRM_USER
 73CONFIG_NET_KEY
 74CONFIG_INET
 75CONFIG_IP_ADVANCED_ROUTER
 76CONFIG_IP_MULTIPLE_TABLES
 77CONFIG_INET_AH
 78CONFIG_INET_ESP
 79CONFIG_INET_IPCOMP
 80CONFIG_INET_XFRM_MODE_TRANSPORT
 81CONFIG_INET_XFRM_MODE_TUNNEL
 82CONFIG_INET_XFRM_MODE_BEET
 83CONFIG_IPV6
 84CONFIG_INET6_AH
 85CONFIG_INET6_ESP
 86CONFIG_INET6_IPCOMP
 87CONFIG_INET6_XFRM_MODE_TRANSPORT
 88CONFIG_INET6_XFRM_MODE_TUNNEL
 89CONFIG_INET6_XFRM_MODE_BEET
 90CONFIG_IPV6_MULTIPLE_TABLES
 91CONFIG_NETFILTER
 92CONFIG_NETFILTER_ADVANCED
 93CONFIG_NETFILTER_NETLINK
 94CONFIG_NETFILTER_NETLINK_ACCT
 95CONFIG_NETFILTER_NETLINK_LOG
 96CONFIG_NETFILTER_NETLINK_QUEUE
 97CONFIG_NETFILTER_TPROXY
 98CONFIG_NETFILTER_XTABLES
 99CONFIG_NETFILTER_XT_CONNMARK
100CONFIG_NETFILTER_XT_MARK
101CONFIG_NETFILTER_XT_MATCH_ADDRTYPE
102CONFIG_NETFILTER_XT_MATCH_CLUSTER
103CONFIG_NETFILTER_XT_MATCH_COMMENT
104CONFIG_NETFILTER_XT_MATCH_CONNBYTES
105CONFIG_NETFILTER_XT_MATCH_CONNLIMIT
106CONFIG_NETFILTER_XT_MATCH_CONNMARK
107CONFIG_NETFILTER_XT_MATCH_CONNTRACK
108CONFIG_NETFILTER_XT_MATCH_CPU
109CONFIG_NETFILTER_XT_MATCH_DCCP
110CONFIG_NETFILTER_XT_MATCH_DEVGROUP
111CONFIG_NETFILTER_XT_MATCH_DSCP
112CONFIG_NETFILTER_XT_MATCH_ECN
113CONFIG_NETFILTER_XT_MATCH_ESP
114CONFIG_NETFILTER_XT_MATCH_HASHLIMIT
115CONFIG_NETFILTER_XT_MATCH_HELPER
116CONFIG_NETFILTER_XT_MATCH_HL
117CONFIG_NETFILTER_XT_MATCH_IPRANGE
118CONFIG_NETFILTER_XT_MATCH_LENGTH
119CONFIG_NETFILTER_XT_MATCH_LIMIT
120CONFIG_NETFILTER_XT_MATCH_MAC
121CONFIG_NETFILTER_XT_MATCH_MARK
122CONFIG_NETFILTER_XT_MATCH_MULTIPORT
123CONFIG_NETFILTER_XT_MATCH_NFACCT
124CONFIG_NETFILTER_XT_MATCH_OSF
125CONFIG_NETFILTER_XT_MATCH_OWNER
126CONFIG_NETFILTER_XT_MATCH_PKTTYPE
127CONFIG_NETFILTER_XT_MATCH_POLICY
128CONFIG_NETFILTER_XT_MATCH_QUOTA
129CONFIG_NETFILTER_XT_MATCH_QUOTA2
130CONFIG_NETFILTER_XT_MATCH_RATEEST
131CONFIG_NETFILTER_XT_MATCH_REALM
132CONFIG_NETFILTER_XT_MATCH_RECENT
133CONFIG_NETFILTER_XT_MATCH_SCTP
134CONFIG_NETFILTER_XT_MATCH_SOCKET
135CONFIG_NETFILTER_XT_MATCH_STATE
136CONFIG_NETFILTER_XT_MATCH_STATISTIC
137CONFIG_NETFILTER_XT_MATCH_STRING
138CONFIG_NETFILTER_XT_MATCH_TCPMSS
139CONFIG_NETFILTER_XT_MATCH_TIME
140CONFIG_NETFILTER_XT_MATCH_U32
141CONFIG_NETFILTER_XT_TARGET_AUDIT
142CONFIG_NETFILTER_XT_TARGET_CHECKSUM
143CONFIG_NETFILTER_XT_TARGET_CLASSIFY
144CONFIG_NETFILTER_XT_TARGET_CONNMARK
145CONFIG_NETFILTER_XT_TARGET_CONNSECMARK
146CONFIG_NETFILTER_XT_TARGET_CT
147CONFIG_NETFILTER_XT_TARGET_DSCP
148CONFIG_NETFILTER_XT_TARGET_HL
149CONFIG_NETFILTER_XT_TARGET_IDLETIMER
150CONFIG_NETFILTER_XT_TARGET_LED
151CONFIG_NETFILTER_XT_TARGET_LOG
152CONFIG_NETFILTER_XT_TARGET_MARK
153CONFIG_NETFILTER_XT_TARGET_NFLOG
154CONFIG_NETFILTER_XT_TARGET_NFQUEUE
155CONFIG_NETFILTER_XT_TARGET_NOTRACK
156CONFIG_NETFILTER_XT_TARGET_RATEEST
157CONFIG_NETFILTER_XT_TARGET_SECMARK
158CONFIG_NETFILTER_XT_TARGET_TCPMSS
159CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP
160CONFIG_NETFILTER_XT_TARGET_TEE
161CONFIG_NETFILTER_XT_TARGET_TPROXY
162CONFIG_NETFILTER_XT_TARGET_TRACE
163CONFIG_NF_CONNTRACK_ZONES
164CONFIG_IP6_NF_FILTER
165CONFIG_IP6_NF_IPTABLES
166CONFIG_IP6_NF_MANGLE
167CONFIG_IP6_NF_MATCH_AH
168CONFIG_IP6_NF_MATCH_EUI64
169CONFIG_IP6_NF_MATCH_FRAG
170CONFIG_IP6_NF_MATCH_HL
171CONFIG_IP6_NF_MATCH_IPV6HEADER
172CONFIG_IP6_NF_MATCH_MH
173CONFIG_IP6_NF_MATCH_OPTS
174CONFIG_IP6_NF_MATCH_RPFILTER
175CONFIG_IP6_NF_MATCH_RT
176CONFIG_IP6_NF_QUEUE
177CONFIG_IP6_NF_RAW
178CONFIG_IP6_NF_SECURITY
179CONFIG_IP6_NF_TARGET_HL
180CONFIG_IP6_NF_TARGET_REJECT
181CONFIG_IP6_NF_TARGET_REJECT_SKERR
182CONFIG_DNS_RESOLVER
183CONFIG_IOSCHED_DEADLINE
184CONFIG_SUSPEND_TIME
185CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS
186CONFIG_CONSOLE_TRANSLATIONS
187CONFIG_EVM
188CONFIG_INTEGRITY_SIGNATURE
189CONFIG_FHANDLE
190CONFIG_EPOLL
191CONFIG_SIGNALFD
192CONFIG_TIMERFD
193CONFIG_TMPFS_POSIX_ACL
194"
195
196CONFIGS_OFF="
197"
198CONFIGS_EQ="
199"
200
201ered() {
202	echo -e "\033[31m" $@
203}
204
205egreen() {
206	echo -e "\033[32m" $@
207}
208
209ewhite() {
210	echo -e "\033[37m" $@
211}
212
213echo -e "\n\nChecking config file for Halium specific config options.\n\n"
214
215errors=0
216fixes=0
217
218for c in $CONFIGS_ON $CONFIGS_OFF;do
219	cnt=`grep -w -c $c $FILE`
220	if [ $cnt -gt 1 ];then
221		ered "$c appears more than once in the config file, fix this"
222		errors=$((errors+1))
223	fi
224
225	if [ $cnt -eq 0 ];then
226		if $write ; then
227			ewhite "Creating $c"
228			echo "# $c is not set" >> "$FILE"
229			fixes=$((fixes+1))
230		else
231			ered "$c is neither enabled nor disabled in the config file"
232			errors=$((errors+1))
233		fi
234	fi
235done
236
237for c in $CONFIGS_ON;do
238	if grep "$c=y\|$c=m" "$FILE" >/dev/null;then
239		egreen "$c is already set"
240	else
241		if $write ; then
242			ewhite "Setting $c"
243			sed  -i "s,# $c is not set,$c=y," "$FILE"
244			fixes=$((fixes+1))
245		else
246			ered "$c is not set, set it"
247			errors=$((errors+1))
248		fi
249	fi
250done
251
252for c in $CONFIGS_EQ;do
253	lhs=$(awk -F= '{ print $1 }' <(echo $c))
254	rhs=$(awk -F= '{ print $2 }' <(echo $c))
255	if grep "^$c" "$FILE" >/dev/null;then
256		egreen "$c is already set correctly."
257		continue
258	elif grep "^$lhs" "$FILE" >/dev/null;then
259		cur=$(awk -F= '{ print $2 }' <(grep "$lhs" "$FILE"))
260		ered "$lhs is set, but to $cur not $rhs."
261		if $write ; then
262			egreen "Setting $c correctly"
263			sed -i 's,^'"$lhs"'.*,# '"$lhs"' was '"$cur"'\n'"$c"',' "$FILE"
264			fixes=$((fixes+1))
265		fi
266	else
267		if $write ; then
268			ewhite "Setting $c"
269			echo  "$c" >> "$FILE"
270			fixes=$((fixes+1))
271		else
272			ered "$c is not set"
273			errors=$((errors+1))
274		fi
275	fi
276done
277
278for c in $CONFIGS_OFF;do
279	if grep "$c=y\|$c=m" "$FILE" >/dev/null;then
280		if $write ; then
281			ewhite "Unsetting $c"
282			sed  -i "s,$c=.*,# $c is not set," $FILE
283			fixes=$((fixes+1))
284		else
285			ered "$c is set, unset it"
286			errors=$((errors+1))
287		fi
288	else
289		egreen "$c is already unset"
290	fi
291done
292
293if [ $errors -eq 0 ];then
294	egreen "\n\nConfig file checked, found no errors.\n\n"
295else
296	ered "\n\nConfig file checked, found $errors errors that I did not fix.\n\n"
297fi
298
299if [ $fixes -gt 0 ];then
300	egreen "Made $fixes fixes.\n\n"
301fi
302
303ewhite " "

编译内核

将处理好的config重命名为.config移动到内核源码目录

编译内核:

# 交叉编译前务必设置环境变量
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

# 配置内核模块压缩为 none,否则 Debian/Arch 不开机
make menuconfig 
make -j$(nproc)

生成 deb 包:

1export ARCH=arm64
2export CROSS_COMPILE=aarch64-linux-gnu-
3export KBUILD_DEBARCH=arm64
4export KDEB_CHANGELOG_DIST=mobile
5make -j$(nproc)  deb-pkg

可选,如不生成,后续构建 rootfs 需要手动复制 vmLinuz。

生成的 deb 包在上级目录下。

构建 rootfs

可以选择使用Arch Linux ARM的官方预构建包

也可以使用 pacstrap 参考 Arch Linux 官方教程来构建root

这里使用预构建包:

1cd ~/vince
2wget http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz

处理 rootfs

释放 rootfs 并挂载需要的目录:

1mkdir rootfs
2sudo tar axf ArchLinuxARM-aarch64-latest.tar.gz -C rootfs
3
4# archlinux 需要挂载自身
5sudo mount --bind ~/vince/rootfs/ ~/vince/rootfs

配置 rootfs

使用 arch-chroot 进入 rootfs 环境:

1sudo arch-chroot rootfs su -
2ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

初始化 pacman keyring

1pacman-key --init
2pacman-key --populate archlinuxarm

卸载内核及 firmware

1pacman -R linux-aarch64 linux-firmware linux-firmware-whence

更新 rootfs:

1pacman -Syu

安装内核

打开一个新终端会话:

1cd ~/vince/linux
2
3sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  INSTALL_MOD_PATH=~/vince/rootfs modules_install
4
5sudo make ARCH=arm64 INSTALL_PATH=~/vince/rootfs/boot install

如果上一步没有构建 deb 包就需要将 arch/arm64/boot 下的 Image.gz 手动复制到 ~/vince/rootfs/boot

安装 firmware

从 pmOS 或者 mobian 的 /lib/firmware 下复制所有文件到 rootfs 的 /lib/firmware

然后回到 rootfs 环境,安装 linux-firmware-qcom:

1pacman -S linux-firmware-qcom

系统及软件配置

参考ArchLinux 安装及 Snapper 和 btrfs-grub 的使用

添加 danctnix 源:

1echo '[danctnix]
2Server = https://p64.arikawa-hi.me/$repo/$arch/' >> /etc/pacman.conf
3
4wget https://p64.arikawa-hi.me/danctnix/aarch64/danctnix-keyring-2-1-any.pkg.tar.xz
5pacman -U danctnix-keyring-2-1-any.pkg.tar.xz
6
7pacman -Syu

前文未提到的必要软件:

1pacman -S networkmanager modemmanager bluez bluez-utils  qrtr rmtfs git wget usbutils
2systemctl enable NetworkManager 
3systemctl enable bluetooth 
4systemctl enable qrtr-ns 
5systemctl enable rmtfs 
6systemctl enable ModemManager

如不安装桌面环境:

1pacman -Sy danctnix-usb-tethering openssh
2systemctl enable usb-tethering
3systemctl enable sshd

可连接 pc 使用RNDIS连接网络,使用 ssh [email protected] 来进行基本的网络配置(这个 ip 我真的,爬了十几分钟 Google)

生成 initrd

kerver=$(ls /usr/lib/modules)
mkinitcpio --generate /boot/initrd.img-$kerver --kernel $kerver

打包镜像

清理缓存:

1pacman -Scc
2cat /dev/null > ~/.bash_history && history -c

随后 Ctrl+D 退出 rootfs

配置文件系统

首先 dd 一个 4G 大小的 raw img,格式化为 ext4(或者你想要的文件系统)

1cd ~/vince
2dd if=/dev/zero of=rootfs.ext4 bs=1M count=4096
3sudo mkfs.ext4 rootfs.ext4

记录刚刚的 UUID 备用,等下使用 file 指令也可获取

同步文件

挂载 rootfs.ext4

1sudo mount rootfs.ext4 -m mnt

使用 rsync 迁移 rootfs :

1rsync -qaHAXS rootfs/ mnt
2sudo umount -R mnt

生成 simg

使用 img2simg 将 raw image 转换为sparse image

1img2simg rootfs.ext4 rootfs.img

这样就得到的最终需要的 rootfs 了

构建 boot

还需要制作一个 boot.img 来启动 rootfs

准备文件:

1mkdir mkboot
2
3cp linux/arch/arm64/boot/Image.gz linux/arch/arm64/boot/dts/qcom/msm8953-xiaomi-vince.dtb mkboot
4
5sudo cp rootfs/boot/initrd.img* mkboot/initrd.img
6
7# 按你自己的用户来
8sudo chown users:users -R mkboot
9cd mkboot

为 kernel 附加设备树:

1cat Image.gz msm8953-xiaomi-vince.dtb > kernel-dtb

生成 boot 镜像:

 1mkbootimg \
 2	--base 0x80000000 \
 3	--kernel_offset 0x00080000 \
 4	--ramdisk_offset 0x02000000 \
 5	--tags_offset 0x01e00000 \
 6	--pagesize 2048 \
 7	--second_offset 0x00f00000 \
 8	--ramdisk initrd.img \
 9	--cmdline "console=tty0 root=UUID=<分区UUID> rw loglevel=3 "\
10	--kernel kernel-dtb -o boot.img

结语

以上,我们就得到了需要的 boot.img 和 rootfs.img ,刷入手机即可 Arch Linux Kernel 6.7.2 aarch64

我也构建了成品放到 GitHub 上:zmyeir/msm8953-archlinux

参考