为手机安装Linux

来自Uotan Wiki · 刷机百科

该章节将引导你为一些手机安装主线Linux操作系统

注意:本教程中,操作环境为64位Ubuntu,目标机器为OnePlus6T,我们将尝试利用UEFI在OnePlus6T上启动Archlinux

  • 不同于Windows, Linux的安装过程可能具有一定的复杂性,步骤繁杂,方案多样,如果你使用不同的机型,请先仔细阅读本文和搜索资料;此外,主线Linux的开发(内核驱动移植,制作dts等)不在本文讨论范畴内。

1 编译内核

sdm845成品: [Releases · silime/kernel-builder (github.com)](https://github.com/silime/kernel-builder)

1.1 安装相关依赖

对于Ubuntu 22.04 LTS:

sudo 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  
sudo apt install gcc-aarch64-linux-gnu dpkg-dev git

1.2 克隆内核源码

你可以在“-b”参数后选择其他分支

mkdir ~/workspace
cd ~/workspace
git clone --depth=1 https://gitlab.com/sdm845-mainline/linux.git -b sdm845/6.8-dev

可用分支可在gitlab网页查看

1.3 生成 .config

make ARCH=arm64 defconfig sdm845.config
# generate .config

1.4 进行编译

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)

生成deb包供Debian系得GNU/Linux使用

make -j$(nproc) ARCH=arm64 KBUILD_DEBARCH=arm64 KDEB_CHANGELOG_DIST=mobile CROSS_COMPILE=aarch64-linux-gnu- deb-pkg
# This will generate several deb files in ../

2 制作rootfs

2.1 下载

对于Archlinux,从http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz下载

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

对于Ubuntu,从 [Index of /ubuntu-base](https://cdimage.ubuntu.com/ubuntu-base/)选择自己想要的版本

2.2 制作

2.2.1 进入chroot

由于rootfs为ARM64,所以安装qemu-user-static

sudo apt install qemu-user-static 

创建img并挂载

dd if=/dev/zero of=archlinux.img bs=1G count=6
mkfs.ext4 archlinux.img
mkdir arch
sudo mount archlinux.img arch

解压

cd arch
sudo tar -xpvf ../ArchLinuxARM-aarch64-latest.tar.gz

进入chroot环境

cd ..
sudo mount --bind /dev arch/dev
sudo mount -t devpts devpts arch/dev/pts -o gid=5,mode=620
sudo mount -t proc proc arch/proc
sudo mount -t sysfs sysfs arch/sys
sudo mount -t tmpfs tmpfs arch/run

sudo rm -rf arch/etc/resolv.conf && sudo cp /etc/resolv.conf arch/etc/

sudo chroot arch
2.2.2 初始化pacman keyring
pacman-key --init
pacman-key --populate archlinuxarm
2.2.3 换源 (可选)

详见 https://mirrors.tuna.tsinghua.edu.cn/help/archlinuxarm/

pacman -Syyu
# upgrade
2.2.4 卸载旧的内核和firmware
pacman -Q | grep -i linux
pacman -R linux-aarch64 linux-firmware linux-firmware-whence

exit
# exit chroot environment
2.2.5 安装新的内核
  • 确保已经退出`chroot`环境

然后:

cd ~/workspace/linux
sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu-  INSTALL_MOD_PATH=~/workspace/arch modules_install
sudo make ARCH=arm64 INSTALL_PATH=~/workspace/arch/boot install

如果是`debian`系也可以直接chroot环境中用dpkg安装deb:dpkg -i *.deb

2.2.6 安装新的firmware
  • 可以尝试从PostmarketOS[1]中提取

进入chroot环境

sudo chroot ~/workspace/arch

移动解压得到的文件

mv * /usr/lib/firmware/
ldconfig

修改/etc/mkinitcpio.conf

nano /etc/mkinitcpio.conf

找到

# BINARIES
# This setting includes any additional binaries a given user may
# wish into the CPIO image.  This is run last, so it may be used to
# override the actual binaries included by a given hook
# BINARIES are dependency parsed, so you may safely ignore libraries
BINARIES=()

在`BINARIES=()`填入`xxxx_zap.mbn/ipa_fws.mbn`的路径 这两个固件的来源一般是手机提取并放在特殊的位置加载(具体由`dts/dtsi`指定) 对于fajita,改为:

 BINARIES=(/usr/lib/firmware/qcom/sdm845/oneplus6/a630_zap.mbn /usr/lib/firmware/qcom/sdm845/oneplus6/ipa_fws.mbn)

生成initrd.img

ls /usr/lib/modules
# get kernel version
mkinitcpio --generate /boot/initrd.img-5.18.0-sdm845-00109-gf7ad1e5036bb-dirty --kernel 5.18.0-sdm845-00109-gf7ad1e5036bb-dirty
2.2.7 安装软件包和基本配置[2]
2.2.7.1 设置时区
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
# Shanghai
2.2.7.2 设置locale

参考:https://wiki.archlinux.org/title/Locale

nano /etc/locale.gen
# uncomment en_US.UTF-8 UTF-8
# uncomment zh_CN.UTF-8 UTF-8

locale-gen
2.2.7.3 自定义主机名
# For example
echo 'OnePlus6T' > /etc/hostname
2.2.7.4 alarm(Archlinuxarm内置非root用户)配置

更改alarm密码,并添加到wheel用户组

passwd alarm
# Change its password. Default is "alarm"

usermod -aG wheel alarm

添加sudo,设置sudo权限

pacman -S sudo
EDITOR=nano visudo
找到下面这样的一行,把前面的注释符号 `#` 去掉
#%wheel ALL=(ALL:ALL) ALL
2.2.7.5 必要软件包
pacman -S base base-devel dhcpcd iwd
pacman -S grub efibootmgr

pacman -S networkmanager modemmanager
pacman -S bluez bluez-utils pulseaudio-bluetooth
pacman -S qrtr rmtfs
systemctl enable NetworkManager bluetooth qrtr-ns rmtfs 
systemctl enable ModemManager
pacman -S git wget
pacman -S ntfs-3g usbutils

再安装 pd-mapper 和 tqftpserv

  • 可以此处下载成品:https://github.com/silime/ArchLinux-Packages
  • 也可以在步骤2.2.7.6后直接用pacman安装!
  • 注:默认的PKGBUILD有问题,需要手动修复,在这里不详细描述,如果嫌麻烦,也可以直接编译安装

a. 直接编译安装(不推荐):

git clone https://github.com/andersson/pd-mapper.git
git clone https://github.com/andersson/tqftpserv.git
cd pd-mapper && make && make install && cd ..
cd tqftpserv && make && make install && cd ..

# clean
rm -rf tqftpserv pd-mapper

b. 使用pkgbuild

# Switch to alarm first
su alarm
cd ~
# Compile and Install pd-mapper
git clone https://aur.archlinux.org/pd-mapper-git.git ~/pd-mapper-git
cd ~/pd-mapper-git

nano PKGBUILD
# fix some errors
makepkg -si

#Compile and Install tqftpserv
git clone https://aur.archlinux.org/tqftpserv-git.git ~/tqftpserv-git
cd ~/tqftpserv-git

nano PKGBUILD
# fix some errors
makepkg -si

启用 pd-mapper 和 tqftpserv

sudo systemctl enable tqftpserv pd-mapper

回到root用户

exit
2.2.7.6 添加Renegade Project源[3](可选)

导入 GPG key:

pacman-key --recv-keys 5E29D8F17064598A7A2223E2C735F8DF5B624511
pacman-key --lsign-key 5E29D8F17064598A7A2223E2C735F8DF5B624511

在 /etc/pacman.conf 文件末尾添加以下内容:

[renegade-project]
Server = https://mirror.renegade-project.tech/arch/$arch

安装 renegade-project-keyring:

pacman -S renegade-project-keyring

刷新

pacman -Syy
2.2.7.7 安装用于切换slot的qbootctl(推荐)
  • 确保已经完成了步骤2.2.7.6
pacman -Sy qbootctl
2.2.7.8 安装更多package使一些硬件工作
2.2.7.9 修改Modemmanager
  • 重新编译ModemManager,开启`plugin_qcom_soc`,并安装
su alarm
mkdir ~/modemmanager
cd ~/modemmanager
nano PKGBUILD
10c10
< arch=(x86_64)
---
> arch=(x86_64 aarch64)
35d34
<     -D plugin_qcom_soc=disabled
  • 编译和安装
makepkg -rsi
# compile and install

cd ..
sudo rm -rf ~/modemmanager
exit
systemctl enable ModemManager
2.2.7.10 其他软件

中文字体

pacman -S noto-fonts-cjk
# Chinese fonts

yay

su alarm
cd ~
git clone https://aur.archlinux.org/yay-bin.git
cd yay-bin && makepkg -si
exit

桌面环境

  • 自选,建议gnome或phosh
    • 如`gnome`
pacman -S gnome
systemctl enable gdm

网络浏览器

# for example, chromium
pacman -S chromium
2.2.8 tfa98xx音频修复
echo 'snd-soc-tfa98xx' > /etc/modules-load.d/snd-soc-tfa98xx.conf
2.2.9 打包

先清理,在chroot环境中

pacman -Scc
# pacman

进alarm用户

su alarm # switch to alarm
# clean bash history for alarm
cat /dev/null > ~/.bash_history && history -c && exit

在root用户

# clean bash history for root
cat /dev/null > ~/.bash_history && history -c

退出chroot环境

exit

解除挂载

cd ~/workspace
sudo umount ~/workspace/arch/run
sudo umount ~/workspace/arch/sys
sudo umount ~/workspace/arch/proc
sudo umount ~/workspace/arch/dev/pts
sudo umount ~/workspace/arch/dev

用tar打包

cd ~/workspace/arch
sudo tar -czvf ~/workspace/arch.tar.gz *
# This will generate arch.tar.gz

3 安装到手机

3.1 刷入twrp和Magisk

  • 你也可以使用KernelSU或其它方式获取root权限

3.2 分区、格式化分区

连接手机、电脑,手机进twrp

将`parted`复制到手机储存

电脑输入:

adb shell

然后输入:

cp /sdcard/parted /sbin/ && chmod 755 /sbin/parted
umount /data && umount /sdcard
parted /dev/block/sda

输入`p`查看当前分区情况

p

对于一加6T,可这样分区:

  • 压缩分区17
resizepart 17
# input 61GB 
  • 创建新分区
mkpart esp fat32 61GB 62GB
mkpart arch ext4 62GB 125GB
set 18 esp on

随后退出parted

q

再次重启到twrp,格式化各分区

电脑输入:

adb shell

然后输入:

mkfs.fat -F32 -s1 /dev/block/by-name/esp
mke2fs -t ext4 /dev/block/by-name/arch
mke2fs -t ext4 /dev/block/by-name/userdata

3.3 获取UUID

重启到Android,在termux或adb shell输入

su
blkid /dev/block/by-name/arch

记下UUID值

3.4 准备grub配置文件

将boot.tar.gz中grub.cfg的uuid全部改为步骤3.3中得到的 替换所有这种字符

3.5 解压rootfs

将arch.tar.gz复制到手机内部存储

  • 建议使用termux操作
pkg update
pkg install tsu

提权

tsu
# root permission needed

挂载&解压

cd ~
mkdir arch
mount /dev/block/by-name/arch ~/arch

cd ~/arch
tar -xpvf /sdcard/arch.tar.gz
# extract

3.6 安装grub

tsu
cd ~
mkdir esp
mount /dev/block/by-name/esp esp
mkdir esp/EFI

将esp.zip中这两个文件夹复制到~/esp/EFI/

将boot.tar.gz内两个文件夹复制进~/arch/boot

  • 检查
# /dev/block/by-name/arch has been mounted!
cd ~/arch/boot && ls

3.7 获取、添加dtb

对于一加6T,还需要将这两个dtb复制到~/arch/boot

  • 注:对于一加6(T)不要使用内核编译生成的dtb
    • 见arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi,将不会有显示

对于其它设备,请获取合适的dtb

/delete-node/ &rmtfs_mem;

/ {
	aliases {
		serial0 = &uart9;
		hsuart0 = &uart6;
	};

	chosen {
		stdout-path = "serial0:115200n8"; /*line 30 in dtsi*/
	};

	volume-keys {
		compatible = "gpio-keys";
		label = "Volume keys";
		autorepeat;
3.7.1 dtb的获取

下载适用自己设备的postmarketOS的boot.img.xz,解压得到img文件

使用 extract-dtb[4]

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple extract-dtb
extract-dtb 20220608-1408-postmarketOS-v22.06-phosh-18-oneplus-fajita-boot.img -o .
# use your own img
# will generate something like 01_dtbdump_,OnePlus_6T.dtb

ls
mv 01_dtbdump_,OnePlus_6T.dtb sdm845-oneplus-fajita.dtb
3.7.2 修改dtb,使得可能支持USB otg

安装dtc工具

sudo apt install device-tree-compiler -y

转换dtb为dts

dtc -I dtb -O dts -o temp.dts sdm845-oneplus-fajita.dtb

修改temp.dts

nano temp.dts

查找`dr_mode`

                        dwc3@a600000 {
                                compatible = "snps,dwc3";
                                reg = <0x00 0xa600000 0x00 0xcd00>;
                                interrupts = <0x00 0x85 0x04>;
                                iommus = <0x25 0x740 0x00>;
                                snps,dis_u2_susphy_quirk;
                                snps,dis_enblslpm_quirk;
                                phys = <0xb8>;
                                phy-names = "usb2-phy";
                                dr_mode = "peripheral";
                                maximum-speed = "high-speed";
                        };

将`peripheral`改为`host` 此时生成的dtb将支持otg,但要外界供电,为了USB主动供电,需要进一步修改,但会导致充电失效 将charger@1000那段删除

                        pmic@2 {
                                compatible = "qcom,pmi8998\0qcom,spmi-pmic";
                                reg = <0x02 0x00>;
                                #address-cells = <0x01>;
                                #size-cells = <0x00>;

                                charger@1000 {
                                        compatible = "qcom,pmi8998-charger";
                                        reg = <0x1000>;
                                        interrupts = <0x02 0x13 0x04 0x03 0x02 0x>
                                        interrupt-names = "usb-plugin\0bat-ov\0wd>
                                        io-channels = <0xdd 0x03 0xdd 0x04>;
                                        io-channel-names = "usbin_i\0usbin_v";
                                        status = "okay";
                                        monitored-battery = <0xde>;
                                };

                                gpios@c000 {
                                        compatible = "qcom,pmi8998-gpio\0qcom,spm>
                                        reg = <0xc000>;
                                        gpio-controller;
                                        gpio-ranges = <0xdf 0x00 0x00 0x0e>;
                                        #gpio-cells = <0x02>;
                                        interrupt-controller;
                                        #interrupt-cells = <0x02>;
                                        phandle = <0xdf>;
                                };

生成新的dtb

dtc -I dts -O dtb -o sdm845-oneplus-fajita-host.dtb temp.dts

复制好dtb,你的usb otg应该就**有可能**工作

4 刷入UEFI

进入bootloader

临时启动

fastboot boot boot-xxx.img

刷入到当前boot分区

fastboot flash boot boot-xxx.img

5 Enjoy!

恭喜你!你已经成功在你的手机上安装Archlinux!!希望你能有所收获!!

5.1 adbd

  • 确保已经添加Renegade Project源
sudo pacman -S adbd

adbd能帮助你用adb调试手机上的Linux

5.2 coremark跑分

yay -S coremark-git
coremark

5.3 unixbench 跑分

========================================================================
   BYTE UNIX Benchmarks (Version 5.1.3)

   System: : GNU/Linux
   OS: GNU/Linux -- 5.18.0-sdm845-00109-gf7ad1e5036bb-dirty -- #1 SMP PREEMPT Thu Jun 2 01:12:20 UTC 2022
   Machine: aarch64 (unknown)
   Language: en_US.utf8 (charmap="UTF-8", collate="UTF-8")
   CPU 0:  (38.4 bogomips)

   CPU 1:  (38.4 bogomips)

   CPU 2:  (38.4 bogomips)

   CPU 3:  (38.4 bogomips)

   CPU 4:  (38.4 bogomips)

   CPU 5:  (38.4 bogomips)

   CPU 6:  (38.4 bogomips)

   CPU 7:  (38.4 bogomips)

   08:08:45 up 4 min,  3 users,  load average: 0.23, 0.15, 0.07; runlevel

------------------------------------------------------------------------
Benchmark Run: Wed Jun 15 2022 08:08:45 - 08:36:48
8 CPUs in system; running 1 parallel copy of tests

Dhrystone 2 using register variables       31371686.9 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                     6636.9 MWIPS (9.9 s, 7 samples)
Execl Throughput                               3464.7 lps   (30.0 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        431850.5 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          212468.6 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1100792.9 KBps  (30.0 s, 2 samples)
Pipe Throughput                             1189114.2 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                  16156.4 lps   (10.0 s, 7 samples)
Process Creation                               1880.5 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                   1267.7 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                    928.5 lpm   (60.0 s, 2 samples)
System Call Overhead                         904143.8 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0   31371686.9   2688.2
Double-Precision Whetstone                       55.0       6636.9   1206.7
Execl Throughput                                 43.0       3464.7    805.7
File Copy 1024 bufsize 2000 maxblocks          3960.0     431850.5   1090.5
File Copy 256 bufsize 500 maxblocks            1655.0     212468.6   1283.8
File Copy 4096 bufsize 8000 maxblocks          5800.0    1100792.9   1897.9
Pipe Throughput                               12440.0    1189114.2    955.9
Pipe-based Context Switching                   4000.0      16156.4     40.4
Process Creation                                126.0       1880.5    149.2
Shell Scripts (1 concurrent)                     42.4       1267.7    299.0
Shell Scripts (8 concurrent)                      6.0        928.5   1547.5
System Call Overhead                          15000.0     904143.8    602.8
                                                                  
========
System Benchmarks Index Score                                         
687.6

------------------------------------------------------------------------
Benchmark Run: Wed Jun 15 2022 08:36:48 - 09:05:10
8 CPUs in system; running 8 parallel copies of tests

Dhrystone 2 using register variables      157010560.9 lps   (10.0 s, 7 samples)
Double-Precision Whetstone                    38380.8 MWIPS (9.5 s, 7 samples)
Execl Throughput                              14684.0 lps   (29.9 s, 2 samples)
File Copy 1024 bufsize 2000 maxblocks        775566.4 KBps  (30.0 s, 2 samples)
File Copy 256 bufsize 500 maxblocks          247697.5 KBps  (30.0 s, 2 samples)
File Copy 4096 bufsize 8000 maxblocks       1947686.0 KBps  (30.0 s, 2 samples)
Pipe Throughput                             6462292.1 lps   (10.0 s, 7 samples)
Pipe-based Context Switching                 535021.4 lps   (10.0 s, 7 samples)
Process Creation                              21863.7 lps   (30.0 s, 2 samples)
Shell Scripts (1 concurrent)                  12727.2 lpm   (60.0 s, 2 samples)
Shell Scripts (8 concurrent)                   1865.6 lpm   (60.1 s, 2 samples)
System Call Overhead                        4647127.5 lps   (10.0 s, 7 samples)

System Benchmarks Index Values               BASELINE       RESULT    INDEX
Dhrystone 2 using register variables         116700.0  157010560.9  13454.2
Double-Precision Whetstone                       55.0      38380.8   6978.3
Execl Throughput                                 43.0      14684.0   3414.9
File Copy 1024 bufsize 2000 maxblocks          3960.0     775566.4   1958.5
File Copy 256 bufsize 500 maxblocks            1655.0     247697.5   1496.7
File Copy 4096 bufsize 8000 maxblocks          5800.0    1947686.0   3358.1
Pipe Throughput                               12440.0    6462292.1   5194.8
Pipe-based Context Switching                   4000.0     535021.4   1337.6
Process Creation                                126.0      21863.7   1735.2
Shell Scripts (1 concurrent)                     42.4      12727.2   3001.7
Shell Scripts (8 concurrent)                      6.0       1865.6   3109.4
System Call Overhead                          15000.0    4647127.5   3098.1
                                                                   
 ========
 System Benchmarks Index Score                                        
 3187.6

6 对一些设备的更多调整

6.1 修复sdm845关机crashdump

sudo nano /etc/systemd/system/shutdown-modem.service

填入

[Unit]
Description=Poweroff modem remoteproc to prevent wlan fw crash
DefaultDependencies=no
Before=shutdown.target

[Service]
Type=oneshot
# remoteproc2 is always the modem on SDM845
ExecStart=echo stop | tee /sys/class/remoteproc/remoteproc*/state

[Install]
WantedBy=shutdown.target

启用服务

sudo systemctl enable shutdown-modem.service

它会在关机前关闭`modem remoteproc`