红米 2#
一台 2015 年初发布的手机,售价 699 元,2024 年居然还没有被遗忘?
硬实力上,红米 2 在当时就不突出。它是闻泰科技 ODM 的产品,从设计到制造都由闻泰完成,配备高通骁龙 410 SoC (MSM8916) ,1GB 运行内存,8GB 存储,4.7 寸 720P 屏幕 (312 ppi) 。MSM8916 采用 28 nm 工艺,CPU 为 4 核 1.2 GHz ARM Cortex-A53,上市之初定位便是中低端,与 2023 年的骁龙旗舰相比性能就只有可怜的 1/10 不到了。作为手机,红米 2 在 2024 年早已没有实用价值,大量红米 2 在闲鱼上的售价仅在 50-100 元之间。
软实力它却很强。红米 2 有非常丰富的第三方 Android 刷机包,出厂搭载 Android 4.4 的它能刷到 Android 10 的 Lineage OS 17.1 (Kernel Version 3.10) 。当它的性能已经不足以支撑在 Android 中多做什么时,它还可以运行接近最新主线的 Linux Kernel 和 Debian, Ubuntu 等正儿八经的 Linux 发行版。可能是得益于高通官方基于 MSM8916 推出了支持 Ubuntu Linux 的 DragonBoard 410c 开发板,也得益于后续开源社区和组织的努力,MSM8916 的主线内核功能已经比较完善,UART、USB、Storage (eMMC/SD card) 、WiFi/Bluetooth、GPU、Display (需要 panel 驱动)、Audio、Buttons、Vibration、Modem (SMS, voice calls with audio, mobile data) 等都得到了支持。
有了完善的 Linux 支持之后,红米 2 作为一个嵌入式 Linux 开发平台瞬间焕发新生。如果应用于只需要极少的 IO,不需要丰富的总线接口,需要利用 USB、 无线通信,甚至还恰好比较需要屏幕交互的场景,相比购买树莓派、香橙派等 Linux 开发板,手机运行 Linux 方案变得性价比极高。因此可以看到红米 2 仍具有很强的生命力,B 站上拿红米 2 做 Klipper 3D 打印上位机的案例非常丰富。同为 MSM8916 SoC 的一些低价随身 WiFi 也纷纷被装上 Linux 做小服务器。
制作过程#
调试#
没有 console log 将是调试的噩梦,能通过串口看 bootloader 和 kernel 的输出非常要紧,否则在屏幕没有成功点亮前就成了黑箱,没有排查空间。而红米 2 有完整的点位图和原理图可看,甚至预留了串口 TP,调试便完全不成问题了。
lk2nd#
lk2nd 是为高通 SoC 开发的基于 Little Kernel 的二级引导程序,可以方便地引导 Linux 启动。而它本身伪装成了 Android 的 boot.img 文件,使得不必改动设备原本 bootloader 就能启动。lk2nd 提供了 fastboot 兼容,可以在电脑用 fastboot 命令实现方便的分区烧写。并且和 u-boot 类似,起到 “兜底” 的作用,不用担心烧进坏的镜像就彻底变砖。
我们直接利用 Release 的 0.15.0 版本 lk2nd-msm8916.img 在原厂 fastboot 中通过以下命令刷入 lk2nd,开机时亮屏后按音量下键可以进入 lk2nd 的 fastboot。
fastboot flash:raw boot lk2nd-msm8916.img
运行 lk2nd 后,烧写便可以使用下面的命令:
fastboot flash boot boot.img
fastboot flash userdata rootfs.img
内核#
从 msm8916-mainline/linux 获取内核,直接编译即可
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
make msm8916_defconfig
make menuconfig
make -j8
make deb-pkg
编译完成后会生成 3 部分的文件:
-
arch/arm64/boot/Image.gz 压缩后的内核映像
-
arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dtb 设备树 dtb,后续需要附在内核映像后
-
../linux-headers-6.7.4-msm8916-dirty_6.7.4-6_arm64.deb 和 ../linux-image-6.7.4-msm8916-dirty_6.7.4-6_arm64.deb 内核头文件和内核的 deb 包,后续需要在根文件系统中安装
将设备树 dtb,附在内核映像后
cat Image.gz msm8916-wingtech-wt88047.dtb > kernel-dtb
Debian rootfs#
首先尝试利用 debootstrap 创建一个 debian 的根文件系统。由于制作所用主机为 amd64 架构,而目标设备为 arm64 架构,需要利用 debootstrap 的 —foreign 选项,并准备 qemu-aarch64-static 用于模拟 arm64 指令集。
apt-get install debootstrap qemu-user-static binfmt-support
debootstrap --arch arm64 --foreign bookworm rootfs http://mirrors.tuna.tsinghua.edu.cn/debian
cp -a /usr/bin/qemu-aarch64-static rootfs/usr/bin/qemu-aarch64-static
然后 chroot 进入刚刚制作的根文件系统,完成 debootstrap 的第二阶段、安装 kernel-image 和 kernel-header,并自由定制自己的根文件系统
mount --bind /dev rootfs/dev
mount --bind /dev/pts rootfs/dev/pts
mount --bind /proc rootfs/proc
chroot rootfs bash
/debootstrap/debootstrap --second-stage
dpkg-reconfigure locales
dpkg -i *.deb #事先拷进来的linux-headers和linux-image
apt update
apt install usbutils network-manager sudo fdisk vim nano openssh-server iputils-ping wget curl iproute2 dialog locales kmod zip unzip u-boot-tools initramfs-tools net-tools htop screenfetch phosh
adduser debian
exit
在安装新 Linux 内核包时,包管理器会调用 update-initramfs 来生成与新内核匹配的 initrd.img 文件,initrd 包含一个临时的根文件系统,运行在内存中负责初始化系统并切换到最终的根文件系统。我们需要拷贝位于 /boot 目录下的 initrd.img-xxx 文件制作进 boot.img 中。
打包 rootfs.img
umount rootfs/dev/pts
umount rootfs/dev
umount rootfs/proc
dd if=/dev/zero of=rootfs.ext4 bs=1M count=4096
mkfs.ext4 rootfs.ext4
mkdir /mnt/rootfs_dd
mount rootfs.ext4 /mnt/rootfs_dd
cp -a rootfs/. /mnt/rootfs_dd/
sync
umount /mnt/rootfs_dd/
img2simg rootfs.ext4 rootfs.img # convert to sparse image
打包 boot.img。在 kernel cmdline 中,通过 UUID 指定 rootfs 分区较为保险,UUID 可以通过file mkfs.ext4
命令查看
mkbootimg --base 0x80000000 \
--kernel_offset 0x00080000 \
--ramdisk_offset 0x02000000 \
--tags_offset 0x01e00000 \
--pagesize 2048 \
--second_offset 0x00f00000 \
--ramdisk initrd.img \
--cmdline "earlycon console=tty0 console=ttyMSM0,115200 root=UUID=b0167571-46ab-432c-9923-46772affcb75 rw loglevel=7"\
--kernel kernel-dtb -o boot.img
Mobian rootfs#
自制的 debian rootfs 可以启动,但图形界面中缺少的东西实在太多,因此转向修改其他机型的 mobian rootfs。mobian 官网下载目前前最新的镜像,得到 mobian-qcom-phosh-20240211.rootfs.img,主要安装上 linux-headers 和 linux-image 即可。
simg2img mobian-qcom-phosh-20240211.rootfs.img mobian-rootfs.img
mount mobian-rootfs.img /mnt/rootfs_dd/
sudo mount --bind /proc /mnt/rootfs_dd/proc
sudo mount --bind /dev /mnt/rootfs_dd/dev
sudo mount --bind /dev/pts /mnt/rootfs_dd/dev/pts
sudo mount --bind /sys /mnt/rootfs_dd/sys
cp linux-headers-6.7.4-msm8916-dirty_6.7.4-6_arm64.deb /mnt/rootfs_dd/tmp/
cp linux-image-6.7.4-msm8916-dirty_6.7.4-6_arm64.deb /mnt/rootfs_dd/tmp/
sudo chroot /mnt/rootfs_dd/
dpkg-reconfigure locales
apt remove qcom-support
dpkg -l | grep -E "linux-headers|linux-image" |awk '{print $2}'|xargs dpkg -P
cd /tmp
dpkg -i *.deb
exit
同样的流程打包 rootfs.img 和 boot.img,烧录即可。
启动后会发现无线不工作,还有屏幕不显示 GUI 但有终端显示的问题。究其原因是缺少了私有的 firmware, 这个部分也容易解决,从其他同机型 rootfs 镜像中直接拷贝即可。GPU Firmware 文件为 a300_pm4.fw 和 a300_pfp.fw, 无线部分有一系列 .mbn 文件和 .bxx 文件。启动后,网络和 GUI 也得以工作。
真正的主线#
msm8916-mainline/linux 这份内核虽然很接近主线,却还不是真正的主线内核 torvalds/linux, 有很多没有合并到主线的修改,版本也略有落后。那么 torvalds/linux 能否跑起来呢,有问题的话能否自行解决修复呢。
通过 git 镜像获取,并安装一些必要的包
git clone https://mirrors.tuna.tsinghua.edu.cn/git/linux-stable.git
git checkout v6.8.0
apt update
apt install -y gcc make gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu libncurses5-dev build-essential pkg-config libc6-dev bison flex libelf-dev lz4 qemu-user-static bc libssl-dev debhelper
主线的内核有 wt88047 的设备树,首先尝试根据msm8916-mainline/linux项目的 msm8916_defconfig 配置内核,编译出一份内核,尝试启动,发现串口能够进入终端,但是屏幕没有正常显示。通过对比 msm8916-mainline/linux 与同版本的 torvalds/linux 之间差距,除了大量的设备树 dts 文件添加与修改,还主要包含了:
-
显示面板驱动 drm/panel 添加与修改
-
drm 和 dsi 部分关于启用禁用逻辑的调整
-
touchscreen, pmic 等外围设备的驱动添加
-
高通 SoC 外设驱动和配置调整,包括 qdsp6, memshare, cpuidle 等
着重添加好面板驱动和显示部分的逻辑,编译内核,用此内核启动后便可以正常看到 phosh 界面了。
总结#
在前人的努力下,在红米 2 上跑起一个比较新的 Linux 系统变得异常轻松,离主线非常近,一切驱动、设备树、config 都已经就绪,只要编译就行,甚至连报错都不带报的。
手机 SoC 的快速迭代实在让人感叹,手机芯片性能已经远甩开嵌入式 Linux 开发中常用的芯片。一个 RK3399 就传了多少年,才有了 RK3588,另外即使是最新的树莓派性能也差强人意,对比一下飞速进步的手机芯片,仿佛不在一个世界。开源的力量也令人倾佩,手机厂商对于手机系统的更新精力有限,老机型没有新机型更新积极几乎必然。更别提支持周期结束之后,不负优化、计划报废就不错了。这在商业上无可厚非。但这也使得手机即使性能硬实力没有太落后,也很难不提早迎来生命的终结。而开源和社区的力量似乎提供了一条让手机发挥更大价值的道路,就如红米 2、一加 6T 等至今依然活跃的老机型,不仅作为手机的生命周期得到延长,甚至还开拓了更加广阔的应用场景,这何尝不是一种更高级的 “环保” 呢。好兆头是,以往芯片公司们常常将资料藏着掖着,而似乎一些公司已在开源方面有了一些动作,骁龙 845、865 等处理器都有了较好的主线内核支持,FOSDEM 2024 中也提到 Linaro 对于高通新旗舰芯片主线支持得越来越快,开放的美好未来似乎就在眼前。
参考资料#
Qualcomm Snapdragon 410/412 (MSM8916) - postmarketOS
DragonBoard 410c - Qualcomm Developer Network
自己 DIY 一个 pinephone——debian 与主线 linux 在红米 2(msm8916)上的移植_红米 2 arm linux-CSDN 博客
自己 DIY 一个 pinephone——debian 与主线 linux 在红米 2(msm8916)上的移植 (二)-CSDN 博客
debootstrap 制作 arm64 位根文件系统 - 掘金 (juejin.cn)
debootstrap 制作根文件系统_debootstrap 嵌入式 - CSDN 博客
随身 wifi 的 Debian 系统固件编译 (knightli.com)
编译内核(debian)・OpenStick 项目・看云 (kancloud.cn)
打造最便宜的骁龙 625Linux 手机 —— 红米 4 移植主线 Linux Mobian Kali Ubuntu_哔哩哔哩_bilibili
ITOP4412---- 尝试使用 debootstrap 构建文件系统。 - 代码先锋网 (codeleading.com)
记一个老年机的逆向工程与主线 linux 移植 (一)—— 信息收集与 Bootloader 移植_msm8909 lk2nd-CSDN 博客