type
status
date
slug
summary
tags
category
icon
password
如果是虚拟机编译内存要求18G及以上(或交换分区
32G
),防止内存不够杀掉编译进程,为什么是18呢,因为试过16G会死(
link-vmlinux.sh
:行 101: 609008 已杀死 ${LD} ${KBUILD_LDFLAGS} -r -o ${1} $(l) …
。如果使用WSL配合docker1. 拉取官方内核
- 安装必要依赖
- 通过
cat /proc/version
查看内核信息
Linux version 4.19.202-g5fbe36ea56f7-ab8008033 (build-user@build-host) (Android (7284624, based on r416183b) clang version 12.0.5 (https://android.googlesource.com/toolchain/llvm-project c935d99d7cf2016289302412d708641d52d2f7ee), LLD 12.0.5 (/buildbot/src/android/llvm-toolchain/out/llvm-project/lld c935d99d7cf2016289302412d708641d52d2f7ee)) #1 SMP PREEMPT Thu Dec 16 06:08:11 UTC 2021
- 在https://source.android.com/docs/setup/build/building-pixel-kernels中查看pixel5设备对应的内核分支信息,这里是最新的分支所以后缀是
android14
,在编译内核时根据自己的系统在https://android.googlesource.com/kernel/manifest/+refs 中寻找对应的内核分支,例如这里选择android-msm-redbull-4.19-android12
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F4850787c-7ae4-4b4a-a5cf-dcf08e54925b%2FUntitled.png?table=block&id=92b744be-2a06-4d06-b7a2-8eab9e8fe52c&t=92b744be-2a06-4d06-b7a2-8eab9e8fe52c&width=680&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F1b1f7638-ec06-476c-928a-5a90f3264af2%2FUntitled.png?table=block&id=a93526db-a0bb-46af-8514-08706fd16576&t=a93526db-a0bb-46af-8514-08706fd16576&width=1464&cache=v2)
- 进入具体的分支,查看其中的
default.xml
,重点关注<project path="build" name="kernel/build"
,如果revision
的值为main
,请千万不要下载,否则你就会发现下载下来之后根本无法build!!,这是由于build仓库和内核源码仓库不同步导致的
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F84270782-dda0-43a1-8612-ae6c9e7c566f%2FUntitled.png?table=block&id=0a7fa903-d22f-43da-8ef0-1a13f60e5e3c&t=0a7fa903-d22f-43da-8ef0-1a13f60e5e3c&width=2331&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F57a318cc-40c6-4e5d-82db-7df4bca0cbb2%2FUntitled.png?table=block&id=381ba5a6-9bba-485c-994a-fc2f65f63f40&t=381ba5a6-9bba-485c-994a-fc2f65f63f40&width=3174&cache=v2)
- 进行内核编译,在这之前需要配置好repo,并且最好配置全局的源为清华源,这部分参照源码编译部分 。
- 等待完成(大概需要60G以上的磁盘空间,耗时两小时左右)后需要进行
checkout
。这里的分支是依据Linux version 4.19.224-gf75e15ae64d0-ab8115056 (build-user@build-host)
中g
后的字符串决定的。
拉取后的源码
git
仓库分为三部分:android-kernel
是拉取源码的根目录,然后是msm-google
以及build
,其中msm-google
是内核源码仓库,任何对内核的更改提交位于该仓库,build
的负责编译的仓库,任何对编译配置等提交位于该仓库。android-kernel
无需add
内容或者提交commit
,msm-google
以及build
在修改后需要进行提交commit
,否则编译的内核会是dirty
的。![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fbb7eba36-c7d2-4645-8704-0cd7f37706f7%2FUntitled.png?table=block&id=38a54677-0bda-440b-9d7a-8ce2848c0dfc&t=38a54677-0bda-440b-9d7a-8ce2848c0dfc&width=936&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F61735623-bc77-49fd-8b23-60481031de63%2FUntitled.png?table=block&id=f94ab618-de3c-4fb1-88e8-6b999e3edb13&t=f94ab618-de3c-4fb1-88e8-6b999e3edb13&width=2141&cache=v2)
2. 提取boot.img-ramdisk.cpio.lz4
- 获取当前系统的
rom
包,从中提取boot.img
,进一步通过https://forum.xda-developers.com/attachments/android-image-kitchen-v3-8-win32-zip.5300919/ 对boot.img
进行解包
- 解压得到的
boot.img-ramdisk.cpio.lz4
并将其放入android-kernel
目录中,低版本的内核可能没有mkbootimg
独立下载http://aospxref.com/android-11.0.0_r21/xref/system/tools/mkbootimg/mkbootimg.py 到android-kernel
- 修改
build.sh
- 在内核源码根目录,进入
build/build.sh
,找到下方代码的位置 - 并在这两行代码之前加上下列命令
然后需要修改编译参数
GKI_RAMDISK_PREBUILT_BINARY
,使得ramdisk
被打包进入boot.img
具体见第六节
3. 嵌入rwProcMem33
- 下载https://github.com/abcz316/rwProcMem33 并将文件夹复制到
android-kernel/private/msm-google/drivers/
中
- 修改
rwProcMem33
中的ver_control.h
将MY_LINUX_VERSION_CODE
切换到对应的安卓内核版本,这里本来就是4.19.224
,与4.19.113
接近所以不需要更改了。
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F569fc3fd-7908-4a7e-962c-323a2b2b7fbc%2FUntitled.png?table=block&id=ed3692cb-64d2-4c9c-bb4a-4a103c5b3c03&t=ed3692cb-64d2-4c9c-bb4a-4a103c5b3c03&width=1042&cache=v2)
- 在
Linux 4.11
前,Linux内核把页表分为4级 - 页全局目录(Page Global Directory,PGD)
- 页上层目录(Page Upper Directory,PUD)
- 页中间目录(Page Middle Directory,PMD)
- 直接页表(Page Table,PT)
所以对于
Linux version 4.11
以下的内核版本,并不支持五级页表,选择启用读取pagemap文件来计算物理内存的地址
,同时注释掉启用页表计算物理内存的地址
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fe1d5e455-e2ab-494f-879c-74944a9acd40%2FUntitled.png?table=block&id=7c5b8580-62f8-4570-8a78-fff0107d9166&t=7c5b8580-62f8-4570-8a78-fff0107d9166&width=878&cache=v2)
Linux version 4.11
版本把页表扩展到五级,在页全局目录和页上层目录之间增加了页四级目录(Page 4th Directory,P4D)。所以对于Linux version 4.11
及以上的内核版本,选择启用页表计算物理内存的地址
,同时注释掉启用读取pagemap文件来计算物理内存的地址
。这里是默认情况,所以不进行更改。![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F256b795a-c197-45f7-b1c1-c41fb51e5ab6%2FUntitled.png?table=block&id=d07bb0af-b1fd-4599-96c6-9816b4ed84b0&t=d07bb0af-b1fd-4599-96c6-9816b4ed84b0&width=680&cache=v2)
- 在
rwProcMem33/linux_kernel_api
文件夹中新建一个头文件linux_kernel_api.h
写入
- 为了包含
linux_kernel_api.h
头文件,在api_proxy.h
的前几行中加入#include "linux_kernel_api/linux_kernel_api.h"
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F667ac4b2-cef3-4c80-9314-549ac2cb08e2%2FUntitled.png?table=block&id=f34c8e9e-5168-4a4c-affa-442f62046f5d&t=f34c8e9e-5168-4a4c-affa-442f62046f5d&width=1450&cache=v2)
- 在
private/msm-google/drivers/Makefile
的开头加入下列命令
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F0aac2881-8d95-4a3f-be36-fa6c149ef6b0%2FUntitled.png?table=block&id=2aa6e9d3-fea6-429e-9865-e13e5b8bbb01&t=2aa6e9d3-fea6-429e-9865-e13e5b8bbb01&width=1378&cache=v2)
- 在编译
rwProcMem33
内核模块时,由于内核编译时会将警告视为错误导致编译内核停止,所以我们要修改Makefile
来忽视warning
。在private/msm-google/Makefile
找到如下位置,在-Wno-format-security
后加上一个-w
参数
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fe0e976c6-c4db-4f9f-b4f1-a00dd36ef223%2FUntitled.png?table=block&id=26c0b14f-4653-441b-83c9-a9ec7ec87819&t=26c0b14f-4653-441b-83c9-a9ec7ec87819&width=1539&cache=v2)
4. 编译内核
在安卓内核源码的根目录打开终端使用如下命令开始编译
命令的参数为使用android-image-kitchen解包boot.img之后,控制台所打印的参数请务必替换为相对应的参数!!!
参数对应关系为
生成的
img
在android-kernel/out
中![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F3c17b0d6-6870-497a-b103-ccec39696171%2FUntitled.png?table=block&id=1b487116-9f89-47a7-8ead-b4c3b2fd1e09&t=1b487116-9f89-47a7-8ead-b4c3b2fd1e09&width=2446&cache=v2)
注意,任何对于kernel源码的改动均需
commit
,如果不进行commit
将会导致内核版本带有dirty
或+
等字样,可能影响环境检测。这里添加了新的rwProcMem33
并且在其内部进行了修改,那么就进入private
目录先add
新内容,再进入rwProcMem33
文件夹手动提交内部模块的commit
,然后在外部进行commit
,直到git status
不出现其他信息5. Magisk修补
将
boot.img
复制到设备中,然后使用设备中的Magisk APP
选择安装修补6. 刷入内核
正常的操作一定是下面这样的,但是实际发现存在问题
刷了整整两天
Pixel5
的内核,包括尝试刷入编译生成的vendor_boot.img
等各种方案,但是很不幸,不是卡google
就是一直循环bootloader
重启。后来看到了参考2中
Droid SMU
的回复。他提示先执行根目录下的build_redbull.sh
进行编译,然后将编译后的kernel/out/android-msm-pixel-4.19/dist/
中的Image.lz4
, Image.lz4-dtb
, kernel-uapi-headers.tar.gz
and all the *.ko kernel modules
从kernel/out/android-msm-pixel-4.19/dist/
复制到 aosp/device/google/redbull-kernel
中(建议先创建该文件夹备份),然后make -j8
编译aosp
。编译完成后将kernel/out/android-msm-pixel-4.19/dist/
中的vendor_boot.img
复制到AOSP目录下out/target/product/redfin
中。然后通过fastboot flashall -w
刷写即可。但是这样是需要编译AOSP的,如何不使用AOSP直接编译内核并替换是个问题,实际经过解img可以发现,
vendor_boot.img
在单独编译和放入aosp编译得到的文件结构是基本一致的,但是boot.img
确有很大差别如下图所示,左侧为内核独立编译后
boot.img
解包后的文件结构,右侧为使用AOSP
编译的内核。![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F5d5bab05-ea4a-4897-a490-389080e5b633%2FUntitled.png?table=block&id=a6b009b5-18fb-4cc8-8e6a-0911d0bcba0c&t=a6b009b5-18fb-4cc8-8e6a-0911d0bcba0c&width=708&cache=v2)
通过查看
MKBOOTIMG
的参数可以发现--ramdisk /android-kernel/prebuilts/boot-artifacts/ramdisks/ramdisk-aosp_arm64.img
指定了一个奇怪的img。再查看
private/msm-google/source/build.config.redbull.common
发现就是GKI_RAMDISK_PREBUILT_BINARY=${ROOT_DIR}/prebuilts/boot-artifacts/ramdisks/ramdisk-aosp_arm64.img
指向的内容,从而使其认为ramdisk
实际是这个img提供的,再看LZ4_RAMDISK=1
那么将GKI_RAMDISK_PREBUILT_BINARY
指向提取的boot.img-ramdisk.cpio.lz4
即可。正确的做法:手动指定
private/msm-google/source/build.config.redbull.common
中的GKI_RAMDISK_PREBUILT_BINARY=${ROOT_DIR}/boot.img-ramdisk.cpio.lz4
这样才会把boot
的ramdisk
打包进入boot.img
在不使用
init_boot
的情况下为设备构建启动映像对于没有init_boot
分区的设备来说,您需要一个 ramdisk 二进制文件,该二进制文件可以通过下载 GKI 启动映像后解压缩来获取。关联的 Android 版本中的任何 GKI 启动映像都可以使用。目标文件夹是内核树的顶级目录(当前的工作目录)。如果您使用 AOSP master 进行开发,则可以从 ci.android.com 上的 aosp_arm64 build 中下载ramdisk-recovery.img
构建工件,并将其用作 ramdisk 二进制文件。当您拥有 ramdisk 二进制文件并将其复制到内核 build 的根目录中的gki-ramdisk.lz4
时,可以通过执行以下命令来生成启动映像:如果您使用的是基于 x86 的架构,请将Image
替换为bzImage
,将aarch64
替换为x86_64
:该文件位于工件目录$KERNEL_ROOT/out/$KERNEL_VERSION/dist
中。启动映像位于out/<kernel branch>/dist/boot.img
。
还有人提到另外的解决方案,但是很显然,在实际测试过程中发现编出的
ko
文件已经被打包进入vendor_boot.img
所以不是这个问题。但是鉴于可能以后会有这样的问题,先把答案留在这。李大锐This is the script I use to launch a custom kernel which is working on pixel 4a. The key isflashing boot.img twice after sending *.ko.I think the the root cause is that the ko file built by the kernel does not enter the boot.img built by aosp. To fundamentally solve this problem a correct boot.img might be needed.
7. 编译HwBpClient客户端
首先在VS installer中安装MFC支持
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fac750e04-1906-45dc-987f-30a0ecf1620e%2FUntitled.png?table=block&id=86b9911f-b583-4f76-b7d3-8a29d15b18f0&t=86b9911f-b583-4f76-b7d3-8a29d15b18f0&width=708&cache=v2)
拉取项目进入
rwProcMem33\hwBreakpointProcModule\testHwBpClient
文件夹,使用vs
打开进行项目编译
在testHwBpClientDlg.cpp
的这个位置进行修改,将这个位置的llX
改为I64X
%zu
改成I64d
,否则将无法正确输入内容。即修改677 - 701
行内容,替换成下面的代码。![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fb3302e35-f9f6-4a36-9384-cef662e39a6a%2FUntitled.png?table=block&id=679f959c-bbfe-4b48-ba9b-aae6f7048f56&t=679f959c-bbfe-4b48-ba9b-aae6f7048f56&width=1939&cache=v2)
使用
ctrl-B
生成exe
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F9428409f-9de3-430d-8153-837d79542aad%2FUntitled.png?table=block&id=1275664c-c9bb-42ec-ba6c-dfdc90b3463a&t=1275664c-c9bb-42ec-ba6c-dfdc90b3463a&width=1409&cache=v2)
8. 编译HwBpServer服务端
编译HwBpServer服务端需要NDK,并将NDK引入环境变量中
NDK可以在
android studio
中进行安装,依次点击File->Project Structure->SDK Location
,找到Android NDK location
,点击Download
即可开始安装,我这里使用的ndk的版本为ndk25.2.9519653
如果没有安装Android studio
,NDK的安装方法可以在谷歌上找到NDK安装完成后,进入到
rwProcMem33\hwBreakpointProcModule\testHwBpServer\jni
,打开cmd运行命令ndk-build
。如果没有添加到环境变量可以直接找到ndk
文件夹中ndk-build.cmd
拖到cmd
或者powershell
中,在jni
目录下执行。编译后的文件在
rwProcMem33\hwBreakpointProcModule\testHwBpServer\libs
中,选择对应手机架构的ELF,push
到手机中运行即可![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2Fb513b6bd-cbdc-4376-99ff-f0111938c086%2FUntitled.png?table=block&id=a5e65698-3c1e-4158-be6b-b2b6e814672a&t=a5e65698-3c1e-4158-be6b-b2b6e814672a&width=708&cache=v2)
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2F3d9d581b-1cbe-449e-9723-f2162662aa76%2F82a800ea-d1a9-406c-bbf1-858683f7e23d%2FUntitled.png?table=block&id=9670405f-53e6-4067-9003-feac6bcb5f86&t=9670405f-53e6-4067-9003-feac6bcb5f86&width=1659&cache=v2)
#参考
- 作者:LLeaves
- 链接:https://lleavesg.top//article/pixel5-kernel-build
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章