构建这个镜像的唯一目的就是我想在手机上实验 Linux namespaces 特性,目前大多数安卓 ROM 内置的内核要么完全不支持这个特性,要么只能支持 Network Namespace
构建的过程看上去是比较简单的,实际上坑却不少(只是我自己的过程总结,如有不对之处请大佬轻拍😜)
-
准备一台安卓手机——除非你准备在模拟器里玩。对于手机厂商的要求就是,至少得开放刷机权限,以及公开内核代码。
-
准备刷机模板——直接用
https://github.com/osm0sis/AnyKernel2,然后 clone 到 out 目录,根据模板的 README 修改刷机脚本。 -
准备构建环境,操作系统 Linux 或者 Macos 均可,我个人建议使用最好的 Linux 发行版—— Windows ,然后根据发行版的不同,下载合适的构建工具(一般如果不是有什么特殊版本要求(这里假设目标环境是 arm64 ,其他的也是同理)的话, linux 和 windows ( WSL )都可以选择下载 https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9 )。
-
下载内核源代码——不作死的话就用厂商自带的,然后检出目标分支到 kernel 目录
-
进入 kernel 目录并设置环境变量,比如
ARCH=arm64和 PATH -
生成默认配置:在 arch 里根据手机型号找到合适 defconfig 文件的文件名——比如 1+3T 就是
arch/arm64/configs/msm-perf_defconfig和arch/arm64/configs/msm-oqc_defconfig,然后我选择了msm-oqc_defconfig作为测试,那么接下来就在代码根目录输入make msm-oqc_defconfig -
魔改配置,直接
make menuconfig,然后根据需要进行修改 -
启动构建
make -j(不作死的话就加个数字) -
等待构建完毕,导出内核模块——
find -name *ko -exec cp "{}" ../out/modules \;;同样也要复制内核镜像文件——
cp arch/arm64/boot/Image.gz-dtb ../out -
打包
cd ../out && zip -r ../flash.zip * -
刷机,进入 TWRP ,开启 sideload 模式,然后
adb sideload flash.zip -
重启,测试各个功能,注意要测试 dmesg 里又没有可疑的输出
遇到的坑有:
-
黑屏——原因有很多,大多数都是构建内核的参数问题——比如弄错了基础配置模板,弄错了 ABI 一类的,仔细看厂商仓库的文件修改时间,应该能找到正确的配置模板的
-
WiFi 不工作 /数据网络无效 /指纹识别无效 /拍照无效 /触控无效——多半是模块没弄上去。。。
-
即使已经把所有的模块都带上了,还是有设备无法工作——我在搞 1+3T 的时候就遇到过 WiFi 始终无法工作的问题,解决方法就是研究厂商的刷机包,看看 system/lib/modules 里面有没有没有涵盖到的模块——比如我那个就是缺少一个 qca-cld 的驱动,解决方法就是
- 找到对应的模块——我在某第三方刷机包里发现 wlan.ko 是一个链接,而链接的目标就是 qca 目录,里面有个 qca-cld-wlan.ko 文件——那不必说,肯定就是 qca-cld 模块了
- 找到模块名字之后,就是把那个模块的独立源代码下载下来,比如我遇到的那个 wifi 驱动,就是直接从 google 的代码库里找到的,然后克隆到某个特定的目录
- 在那个目录里执行构建模块任务——
make KERNEL_SRC=~/data/kernel -j - 得到构建到的目标内核模块,加入到 modules 里,重新打包刷机
-
各种编译错误:多数是符号定义的问题,由于构建系统的复杂性,搞清楚整个构建系统对我来说,还不如直接批量修改源代码,比如把一部分
#include<>改成#include"",或者在#include""里加上相对路径,或者修改某些宏定义一类的。诚然,修改 Makefile 应该是更好的选择,奈何复杂度太高。
FAQ:
-
为啥使用AnyKernel这种方式构造刷机包?
两个字:简单
不用去纠结 boot.img 中到底应该设置多少偏移量一类的操蛋问题
