紅米 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 博客