首页
社区
课程
招聘
Android10 内核编译笔记
2023-5-14 23:35 13288

Android10 内核编译笔记

2023-5-14 23:35
13288

前言

这几天在踩内核编译的坑,笔者虽然参考了许多帖子,但由于谷歌今年更新了内核编译的方法,也就是说一年前的文章参考意义不大,而今年的文章总是会有些许描述模糊或遗漏的地方,众所周知内核编译这个东西稍有差池等于失败,所以本文会尽可能详细的记录每一步的操作,希望后续的人少走一些弯路

环境配置

环境 配置
VMware 16.1.1 build-17801498
Ubuntu Ubuntu 20.04.2 LTS
物理机内存 32G
虚拟机内存 16G
物理机储存 2T
虚拟机内存 1T
目标机型 Pixel 4
目标版本 Android 10
分支版本 android-10.0.0_r9

下载内核源码

正常来讲在 https://source.android.com/setup/building-kernels 中应该可以查询到 pixel4 的内核

1
Pixel 4 (flame)   device/google/coral-kernel    android-msm-coral-4.14-android13

但在这里对于萌新有个坑,官网只给出了 android13 的内核,我们要编译的 android10 在哪里?(这里踩了个大坑,我最开始一直以为这个 git 包含了4-13的所有分支,最离谱的是还能正常 check out android 10 的分支)访问 https://android.googlesource.com/kernel/manifest/+refs 搜索 android-msm-coral-4.14-android 我们可以得到如下信息,与 android10 匹配的共有四条,之间区别不太清楚,有知晓的大佬可以告知下,先行谢过,笔者这里亲测 android10-qpr3 是可用的

1
2
3
4
5
6
7
8
9
10
11
12
android-msm-coral-4.14-android10
android-msm-coral-4.14-android10-c2f2
android-msm-coral-4.14-android10-qpr1
android-msm-coral-4.14-android10-qpr3
android-msm-coral-4.14-android11
android-msm-coral-4.14-android11-qpr2
android-msm-coral-4.14-android11-qpr3
android-msm-coral-4.14-android12
android-msm-coral-4.14-android12-qpr1
android-msm-coral-4.14-android12-v2-beta-2
android-msm-coral-4.14-android12L
android-msm-coral-4.14-android13

在可以科学上网的情况,我们可以使用下方的命令获取内核源码

1
repo init -u https://android.googlesource.com/kernel/manifest -b android-msm-coral-4.14-android10-qpr3

为了加速下载,当然是使用国内的镜像

1
2
echo "REPO_URL='https://gerrit-googlesource.proxy.ustclug.org/git-repo'" >> ~/.bashrc
source ~/.bashrc

但有时候使用了上方的配置还是会失败,笔者这里选择一劳永逸直接修改 repo 文件,在约 130 行处替换 https://gerrit.googlesource.com/git-repo 为 https://gerrit-googlesource.proxy.ustclug.org/git-repo

1
gedit ~/bin/repo

禁用 ssl 验证,否则会失败

1
2
git config --global http.sslverify false
git config --global https.sslverify false

设置拉取的目标文件,这里同样使用国内的镜像源

1
2
3
4
5
6
7
8
9
10
11
12
13
mkdir ~/bin/android-kernel && cd ~/bin/android-kernel
 
repo init -u git://mirrors.ustc.edu.cn/aosp/kernel/manifest -b android-msm-coral-4.14-android10-qpr3
 
--------------------------------------------------------------------
注意:下面的提示表示更新成功,并不是报错
Downloading Repo source from https://gerrit-googlesource.proxy.ustclug.org/git-repo
repo: Updating release signing keys to keyset ver 2.3
 
Your identity is: lxz <211527456@qq.com>
If you want to change this, please re-run 'repo init' with --config-name
 
repo has been initialized in /home/lxz/bin

拉取内核源码

1
repo sync

查询手机内核版本

为了在众多内核中准确找到我们真机对应的内核版本,可以在真机系统中输入以下命令查询 short commit id,其中 4.14.111-g 后边的为 short commit id

1
2
3
flame:/ # cat proc/version
-----------------------------------------------
Linux version 4.14.111-gb3ac0fc2b0f7-ab5912761 (android-build@abfarm-us-east1-c-0082) (Android (5484270 based on r353983c) clang version 9.0.3 (https://android.googlesource.com/toolchain/clang 745b335211bb9eadfa6aa6301f84715cee4b37c5) (https://android.googlesource.com/toolchain/llvm 60cf23e54e46c807513f7a36d0a7b777920b5881) (based on LLVM 9.0.3svn)) #1 SMP PREEMPT Tue Oct 1 23:35:30 UTC 2019

编译内核源码

如果当前的环境并未编译过 android 源码,那么需要配置如下的环境依赖,已经编译过 android 的源码那么可以跳过此步骤

1
sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig libncurses5

在安装完上述依赖后,不论你是否编译过 android 源码都还需再安装 libssl-dev

1
sudo apt-get install libssl-dev

切换到我们手机当前版本的内核源码分支

1
2
cd ~/bin/android-kernel/private/msm-google
git checkout b3ac0fc2b0f7

执行编译脚本,编译完成后的镜像 Image.lz4 存放在 ~/bin/android-kernel/out/android-msm-floral-4.14/dist 目录中

1
~/bin/android-kernel/build/build.sh

编译时遇到报错

1
2
3
./security/selinux/include/classmap.h:245:2: error: #error New address family defined, please update secclass_map.
#error New address family defined, please update secclass_map.
-git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c:

解决方案参考 编译错误 error New address family defined, please update secclass_map.解决

  • 找到错误中提示的 genheaders.c 文件和 mdp.c 文件,去掉两个文件的头部引用中的 #include <sys/socket.h>

    1
    2
    gedit ~/bin/android-kernel/private/msm-google/scripts/selinux/genheaders/genheaders.c
    gedit ~/bin/android-kernel/private/msm-google/scripts/selinux/mdp/mdp.c
  • 找到错误提示中的 classmap.h 文件,第三行处添加 #include <linux/socket.h>

    1
    gedit ~/bin/android-kernel/private/msm-google/security/selinux/include/classmap.h

修复触屏

如果你此时将 Image.lz4 文件直接替换为 aosp 中的 Image.lz4 就直接编译刷机,那么你将得到一部触屏失效的 Pixel 4,所以还需要一些处理,方法主要参考 eBPF on Android之编译内核与打补丁(解决触摸和WIFI失效问题),大佬的帖子里有修复原理的详细分析,感谢 seeeseee 大佬的分享,但大佬的帖子中包含了 eBPF 的开启,我们这里暂时不需要,步骤会做一些精简。我的理念是一步一步操作,如果遇到问题,可以即时的发现问题,如果一次性操作太多,一旦出现问题就很难定位,所以我建议你先将触屏失效的手机做出来再解决触屏失效的问题。

解包 boot.img

使用 Android-Image-Kitchen 解包手机当前使用的 boot.img(boot.img 拖到 unpackimg.bat 即可),此时我们可以得到如下信息(信息拷贝一份留着有用),以及 split_img\boot.img-ramdisk.cpio.gz,我们手动将 split_img\boot.img-ramdisk.cpio.gz 解压,将得到的 boot.img-ramdisk.cpio 文件拷贝到 ~/bin/android-kernel 目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ANDROID! magic found at: 0
BOARD_KERNEL_CMDLINE console=ttyMSM0,115200n8 androidboot.console=ttyMSM0 printk.devkmsg=on msm_rtb.filter=0x237 ehci-hcd.park=3 service_locator.enable=1 androidboot.memcg=1 cgroup.memory=nokmem usbcore.autosuspend=7 androidboot.usbcontroller=a600000.dwc3 swiotlb=2048 androidboot.boot_devices=soc/1d84000.ufshc buildvariant=userdebug
BOARD_KERNEL_BASE 0x00000000
BOARD_NAME
BOARD_PAGE_SIZE 4096
BOARD_HASH_TYPE sha1
BOARD_KERNEL_OFFSET 0x00008000
BOARD_RAMDISK_OFFSET 0x01000000
BOARD_SECOND_OFFSET 0x00f00000
BOARD_TAGS_OFFSET 0x00000100
BOARD_OS_VERSION 10.0.0
BOARD_OS_PATCH_LEVEL 2019-10
BOARD_HEADER_VERSION 2
BOARD_HEADER_SIZE 1660
BOARD_DTB_SIZE 1002744
BOARD_DTB_OFFSET 0x01f00000

配置 mkbootimg 脚本

mkbootimg.py 拷贝到 /home/lxz/bin/android-kernel 目录下

修改脚本文件

打开脚本文件 build.sh

1
gedit ~/bin/android-kernel/build/build.sh

在约 396 行处添加代码,作用是将boot.img-ramdisk.cpio复制到产物目录下,参与后续打包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Copy the abi_${arch}.xml file from the sources into the dist dir
if [ -n "${ABI_DEFINITION}" ]; then
  echo "========================================================"
  echo " Copying abi definition to ${DIST_DIR}/abi.xml"
  pushd $ROOT_DIR/$KERNEL_DIR
    cp "${ABI_DEFINITION}" ${DIST_DIR}/abi.xml
  popd
fi
 
# //add
if [ -f "${VENDOR_RAMDISK_BINARY}" ]; then
  cp ${VENDOR_RAMDISK_BINARY} ${DIST_DIR}
fi
# //add
 
echo "========================================================"
echo " Files copied to ${DIST_DIR}"

编译内核

KERNEL_CMDLINE、BASE_ADDRESS、PAGE_SIZE 的值来自于上边的解包信息,过程中会在LTO vmlinux.o 这里卡一段时间并报警告,多多多多多多等一会儿即可,编译完成后的镜像 Image.lz4 存放在 ~/bin/android-kernel/out/android-msm-floral-4.14/dist 目录中

1
2
3
cd ~/bin/android-kernel
 
BUILD_CONFIG=private/msm-google/build.config BUILD_BOOT_IMG=1 MKBOOTIMG_PATH=mkbootimg.py VENDOR_RAMDISK_BINARY=boot.img-ramdisk.cpio KERNEL_BINARY=Image.lz4 BOOT_IMAGE_HEADER_VERSION=2 KERNEL_CMDLINE="console=ttyMSM0,115200n8 androidboot.console=ttyMSM0 printk.devkmsg=on msm_rtb.filter=0x237 ehci-hcd.park=3 service_locator.enable=1 androidboot.memcg=1 cgroup.memory=nokmem usbcore.autosuspend=7 androidboot.usbcontroller=a600000.dwc3 swiotlb=2048 androidboot.boot_devices=soc/1d84000.ufshc buildvariant=userdebug" BASE_ADDRESS=0x00000000 PAGE_SIZE=4096 build/build.sh

重打包 boot.img

将 Image.lz4 重命名为 boot.img-kernel,拷贝到 Android Image Kitchen\split_img 目录下替换原本的 boot.img-kernel,此时执行 repackimg.bat 会得到 image-new.img,执行下方的命令将其刷入手机,此时等待手机重启即可

1
2
3
adb reboot bootloader
fastboot flash image-new.img
fastboot reboot

添加 Log

既然我们已经成功的编译内核了,那我们有理由选择留下一些自己的内核 Log,比如说通过修改函数 do_sys_open

1
gedit ~/bin/android-kernel/private/msm-google/fs/open.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
    struct open_flags op;
    int fd = build_open_flags(flags, mode, &op);
    struct filename *tmp;
 
    // add
    const struct cred *cred = current_cred();
    kuid_t uid = cred->uid;
    int pid = current->pid;
    int myuid = uid.val;
    if(myuid > 10000) {
        char bufname[256]={0};
        strncpy_from_user(bufname, filename, 255);
        printk("lxzLog do_sys_open pathname:%s  uid:%d pid:%d\n", bufname, myuid, pid);
    }
    // add
 
    if (fd)
        return fd;
 
    tmp = getname(filename);
    if (IS_ERR(tmp))
        return PTR_ERR(tmp);
 
    fd = get_unused_fd_flags(flags);
    if (fd >= 0) {
        struct file *f = do_filp_open(dfd, tmp, &op);
        if (IS_ERR(f)) {
            put_unused_fd(fd);
            fd = PTR_ERR(f);
        } else {
            fsnotify_open(f);
            fd_install(fd, f);
        }
    }
    putname(tmp);
    return fd;
}

重新编译内核刷进手机,在 cmd (power shell 不支持 &)中直接使用如下的命令就可以查看属于自己的内核 Log 了

1
2
3
4
5
6
7
8
9
adb root & adb shell dmesg | findstr lxzLog
--------------------------------------------------------------------
[5.973256] lxzLog do_sys_open pathname:/proc/1662/timerslack_ns  uid:10094 pid:1662
[5.973305] lxzLog do_sys_open pathname:/proc/thread-self/attr/current  uid:10094 pid:1662
[5.973454] lxzLog do_sys_open pathname:/sys/fs/selinux/context  uid:10094 pid:1662
[5.974109] lxzLog do_sys_open pathname:/proc/thread-self/attr/current  uid:10094 pid:1662
[5.975541] lxzLog do_sys_open pathname:/sys/devices/system/cpu/online  uid:10094 pid:1662
[5.978139] lxzLog do_sys_open pathname:/proc/self/cmdline  uid:10094 pid:1662
[5.979101] lxzLog do_sys_open pathname:/dev/binder  uid:10094 pid:1662

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

最后于 2023-5-27 16:08 被简单的简单编辑 ,原因:
收藏
免费 10
打赏
分享
最新回复 (14)
雪    币: 1826
活跃值: (9144)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
你瞒我瞒 2023-5-17 14:22
2
0
TQL
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
翻手为云 2023-5-26 23:45
3
0
我死活成功不了,我用原来好的64MB大小的boot.img unpack后,啥也不改,直接repack生成的img,然后文件大小就从只剩25M,不知道是不是我Android Image Kitchen工具的原因,还是本来就这样
雪    币: 5021
活跃值: (3148)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
vigiles 2023-5-27 01:19
4
0
火钳刘明。只编过lineageos
雪    币: 5774
活跃值: (4099)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
简单的简单 2023-5-27 14:56
5
0
翻手为云 我死活成功不了,我用原来好的64MB大小的boot.img unpack后,啥也不改,直接repack生成的img,然后文件大小就从只剩25M,不知道是不是我Android Image Kitchen ...
帖子里有提供我使用的 Android Image Kitchen 你可以试一下
雪    币: 20199
活跃值: (29735)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-5-27 18:26
6
1
感谢分享
雪    币: 1809
活跃值: (509)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
ranshu 2023-5-27 20:20
7
0
谢谢分享。
雪    币: 107
活跃值: (1467)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
frozenrain 2023-12-8 10:21
8
0
所以为啥单独编译会无法boot,而官方的包却OK。我尝试了一下Android 13,编出来的无法boot,刷机的时候就卡在boot那一步。解包出来对比区别就是比官方的kernel 少5M,不知道缺了啥东西。
雪    币: 5774
活跃值: (4099)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
简单的简单 2023-12-8 10:26
9
0
frozenrain 所以为啥单独编译会无法boot,而官方的包却OK。我尝试了一下Android 13,编出来的无法boot,刷机的时候就卡在boot那一步。解包出来对比区别就是比官方的kernel 少5M,不知道缺了啥 ...
这只能说只有谷歌知道了,谷歌的东西总是这样,坑的很
雪    币: 107
活跃值: (1467)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
frozenrain 2023-12-9 17:28
10
0

对比了一下ramdisk内容也不一样,按照楼主的方法生成的boot.img只有45M左右,这个用fastboot boot boot.img无法启动。最后去aosp目录make了一下,最后不知啥原因能到fastbootd那一步了,再后来整个fastboot刷完了,突然就好了。我是pixel 4 Android13,这里面唯一的区别感觉就是之前kernel指向Image.lz4-dtb,后来换成了Image.lz4。

最后于 2023-12-9 17:32 被frozenrain编辑 ,原因:
雪    币: 92
活跃值: (301)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wois杨 2023-12-17 16:59
11
0
frozenrain 对比了一下ramdisk内容也不一样,按照楼主的方法生成的boot.img只有45M左右,这个用fastboot&nbsp;boot&nbsp;boot.img无法启动。最后去aosp ...
我跟你一样的情况,请问怎么make的?
雪    币: 107
活跃值: (1467)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
frozenrain 2024-2-4 09:49
12
0

我最近换了个ubuntu版本,结果发现突然又不行了。其实我也没完全搞清楚,修改kernel指向Image.lz4,Image.lz4-dtb,多尝试几次?

最后于 2024-2-4 09:50 被frozenrain编辑 ,原因:
雪    币: 1416
活跃值: (9782)
能力值: ( LV9,RANK:240 )
在线值:
发帖
回帖
粉丝
misskings 4 2024-2-4 17:18
13
0
解决了。可行的。不过和你说的有一些误差。比如我这边Image.lz4拷贝替换后。重新打包回boot.img,也是一样触摸失效的。但是我通过前面build/build.sh命令编译出来的目录下直接就有boot.img了。这个img使用就是触摸正常的。
雪    币: 17
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
刘宽森 3天前
14
0
大佬 有安卓 12 的内核编译吗  编译出来开机屏幕动不了
雪    币: 5774
活跃值: (4099)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
简单的简单 1天前
15
0
刘宽森 大佬 有安卓 12 的内核编译吗 编译出来开机屏幕动不了
后续发现其实触摸失效的本质原因其实是 vendor.img 的问题,修改 boot.img 有点本末倒置的意思,你可以尝试一下编译 vendor.img
游客
登录 | 注册 方可回帖
返回