Redmi 2#
A phone released in early 2015, priced at 699 yuan, and surprisingly not forgotten by 2024?
In terms of hardware, the Redmi 2 was not outstanding at the time. It is a product of Wingtech Technology ODM, with design and manufacturing completed by Wingtech, equipped with a Qualcomm Snapdragon 410 SoC (MSM8916), 1GB of RAM, 8GB of storage, and a 4.7-inch 720P screen (312 ppi). The MSM8916 uses a 28 nm process, with a 4-core 1.2 GHz ARM Cortex-A53 CPU, initially positioned as mid-range. Compared to the Snapdragon flagship in 2023, its performance is a pitiful less than 1/10. As a phone, the Redmi 2 has long lost its practical value by 2024, with many units on second-hand platforms selling for only 50-100 yuan.
However, it has strong software capabilities. The Redmi 2 has a very rich variety of third-party Android ROMs, and it can be upgraded from the factory-installed Android 4.4 to Android 10's Lineage OS 17.1 (Kernel Version 3.10). When its performance is no longer sufficient to support much in Android, it can still run nearly the latest mainline Linux Kernel and proper Linux distributions like Debian and Ubuntu. This is likely due to Qualcomm's official release of the DragonBoard 410c development board supporting Ubuntu Linux based on the MSM8916, as well as the efforts of the subsequent open-source community and organizations. The mainline kernel features of MSM8916 have become quite complete, supporting UART, USB, Storage (eMMC/SD card), WiFi/Bluetooth, GPU, Display (requires panel driver), Audio, Buttons, Vibration, Modem (SMS, voice calls with audio, mobile data), etc.
With complete Linux support, the Redmi 2 has been revitalized as an embedded Linux development platform. If applied in scenarios that require minimal I/O, do not need rich bus interfaces, and need to utilize USB and wireless communication, especially where screen interaction is somewhat necessary, running Linux on a phone becomes a cost-effective solution compared to purchasing Linux development boards like Raspberry Pi or Orange Pi. Therefore, it can be seen that the Redmi 2 still has strong vitality, with many cases on Bilibili using the Redmi 2 as a Klipper 3D printing host. Some low-cost portable WiFi devices with the MSM8916 SoC have also been equipped with Linux to serve as small servers.
Production Process#
Debugging#
Not having a console log would be a debugging nightmare; being able to view the bootloader and kernel output via serial is crucial, otherwise, it becomes a black box before the screen successfully lights up, leaving no room for troubleshooting. The Redmi 2 has a complete pinout diagram and schematic available, and even reserves a serial TP, making debugging completely manageable.
lk2nd#
lk2nd is a secondary bootloader based on Little Kernel developed for Qualcomm SoCs, which can conveniently boot Linux. It disguises itself as an Android boot.img file, allowing it to boot without modifying the device's original bootloader. lk2nd provides fastboot compatibility, allowing convenient partition flashing using fastboot commands on a computer. Similar to u-boot, it acts as a "fallback," so there is no need to worry about bricking the device by flashing a bad image.
Project address: msm8916-mainline/lk2nd: Custom bootloader for Qualcomm MSM8916/MSM8226/MSM8974/... devices (github.com)
We directly used the Release version 0.15.0 lk2nd-msm8916.img and flashed it using the following command in the original factory fastboot, pressing the volume down key after the screen lights up to enter lk2nd's fastboot.
fastboot flash:raw boot lk2nd-msm8916.img
After running lk2nd, flashing can be done using the following commands:
fastboot flash boot boot.img
fastboot flash userdata rootfs.img
Kernel#
Obtain the kernel from msm8916-mainline/linux and compile it directly.
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
make msm8916_defconfig
make menuconfig
make -j8
make deb-pkg
After compilation, three parts of files will be generated:
-
arch/arm64/boot/Image.gz - the compressed kernel image
-
arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dtb - device tree dtb, which needs to be appended to the kernel image later
-
../linux-headers-6.7.4-msm8916-dirty_6.7.4-6_arm64.deb and ../linux-image-6.7.4-msm8916-dirty_6.7.4-6_arm64.deb - kernel header files and kernel deb packages, which need to be installed in the root filesystem later.
Append the device tree dtb to the kernel image.
cat Image.gz msm8916-wingtech-wt88047.dtb > kernel-dtb
Debian rootfs#
First, try to create a Debian root filesystem using debootstrap. Since the host used for production is amd64 architecture while the target device is arm64 architecture, the --foreign option of debootstrap is needed, and qemu-aarch64-static is prepared to simulate the arm64 instruction set.
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
Then chroot into the newly created root filesystem to complete the second stage of debootstrap, install kernel-image and kernel-header, and customize your root filesystem freely.
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 # previously copied linux-headers and 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
When installing the new Linux kernel package, the package manager will call update-initramfs to generate the initrd.img file that matches the new kernel. The initrd contains a temporary root filesystem that runs in memory, responsible for initializing the system and switching to the final root filesystem. We need to copy the initrd.img-xxx file located in the /boot directory into boot.img.
Pack 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
Pack boot.img. It is safer to specify the rootfs partition via UUID in the kernel cmdline, which can be checked using the file mkfs.ext4
command.
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#
The homemade Debian rootfs can boot, but there are too many missing elements in the graphical interface, so we turn to modify the Mobian rootfs of other models. Download the latest image from the Mobian official website, obtaining mobian-qcom-phosh-20240211.rootfs.img, mainly installing linux-headers and 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
The same process is used to pack rootfs.img and boot.img, and then flash them.
After booting, it is found that the wireless does not work, and the screen does not display the GUI but shows terminal output. The reason is that the proprietary firmware is missing, which can be easily resolved by copying it directly from other rootfs images of the same model. The GPU firmware files are a300_pm4.fw and a300_pfp.fw, and there are a series of .mbn files and .bxx files for the wireless part. After booting, both the network and GUI become functional.
The Real Mainline#
The kernel from msm8916-mainline/linux is very close to the mainline but is not the true mainline kernel torvalds/linux, as it has many modifications that have not been merged into the mainline, and the version is slightly outdated. So can torvalds/linux run? If there are issues, can they be resolved and fixed independently?
Obtain the git mirror and install some necessary packages.
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
The mainline kernel has the device tree for wt88047. First, try to configure the kernel based on the msm8916_defconfig from the msm8916-mainline/linux project, compile a kernel, and attempt to boot. It is found that the serial port can enter the terminal, but the screen does not display normally. By comparing the differences between msm8916-mainline/linux and the same version of torvalds/linux, it is noted that besides numerous additions and modifications to the device tree dts files, it mainly includes:
-
Display panel driver additions and modifications in drm/panel
-
Adjustments in drm and dsi regarding enable/disable logic
-
Additions of drivers for peripherals like touchscreen and pmic
-
Adjustments to Qualcomm SoC peripheral drivers and configurations, including qdsp6, memshare, cpuidle, etc.
Focusing on adding the panel driver and display logic, compile the kernel, and after booting with this kernel, the phosh interface can be seen normally.
Summary#
Thanks to the efforts of predecessors, running a relatively new Linux system on the Redmi 2 has become exceptionally easy, very close to the mainline, with all drivers, device trees, and configurations ready; all that is needed is to compile, and there are hardly any errors.
The rapid iteration of mobile SoCs is truly astonishing; the performance of mobile chips has far surpassed those commonly used in embedded Linux development. It took how many years for an RK3399 to emerge, and only then did we see the RK3588. Moreover, even the latest Raspberry Pi's performance is somewhat lacking. Comparing it to the rapidly advancing mobile chips, it seems they are not in the same world. The power of open source is also admirable; mobile manufacturers have limited energy for updating mobile systems, and older models are almost inevitably less proactive in receiving updates compared to new models. Not to mention that after the support period ends, it is already good enough if they do not neglect optimization and plan for obsolescence. This is commercially understandable. However, this also means that even if the mobile performance does not lag too far behind, it is difficult to avoid an early end to its life cycle. The power of open source and community seems to provide a path for mobile phones to realize greater value, just like the Redmi 2 and OnePlus 6T, which are still active old models, not only extending the lifecycle of the phone but also exploring broader application scenarios. Isn't this a more advanced form of "environmental protection"? The good news is that in the past, chip companies often kept their information hidden, but it seems that some companies have begun to make moves in the open-source area. Processors like Snapdragon 845 and 865 have received good mainline kernel support, and Linaro's support for Qualcomm's new flagship chips is getting faster, as mentioned in FOSDEM 2024. A beautiful open future seems to be just around the corner.
References#
Qualcomm Snapdragon 410/412 (MSM8916) - postmarketOS
DragonBoard 410c - Qualcomm Developer Network
DIY a PinePhone - Porting Debian and Mainline Linux to Redmi 2 (msm8916) - CSDN Blog
DIY a PinePhone - Porting Debian and Mainline Linux to Redmi 2 (msm8916) Part 2 - CSDN Blog
Creating an arm64 Root Filesystem with debootstrap - Juejin
Creating a Root Filesystem with debootstrap - CSDN Blog
Debian System Firmware Compilation for Portable WiFi - Knightli
Compiling Kernel (Debian) - OpenStick Project - Kancloud
ITOP4412 - Attempting to Build a Filesystem with debootstrap - Code Leading