1 分钟阅读 次阅读

问题

首次编译3588 Android SDK时出现编译错误,日志如下:

'out/target/product/rk3588_RB/system_ext/etc/vintf/manifest.xml': OK
checkvintf I 06-05 16:06:03  8701  8701 HostFileSystem.cpp:54] List 'out/target/product/rk3588_RB/product/etc/vintf/': NAME_NOT_FOUND
checkvintf I 06-05 16:06:03  8701  8701 check_vintf.cpp:384] All HALs in device manifest are declared in FCM <= level 6
checkvintf E 06-05 16:06:03  8701  8701 check_vintf.cpp:620] files are incompatible: Runtime info and framework compatibility matrix are incompatible: No compatible kernel requirement found (kernel FCM version = 6).
checkvintf E 06-05 16:06:03  8701  8701 check_vintf.cpp:620] For kernel requirements at matrix level 6, For config CONFIG_DEVMEM, value = y but required n
checkvintf E 06-05 16:06:03  8701  8701 check_vintf.cpp:620] : Success
INCOMPATIBLE
16:06:06 ninja failed with: exit status 1
ninja: build stopped: subcommand failed.

#### failed to build some targets (07:25 (mm:ss)) ####

Build android failed!

问题分析

  • 日志中check_vintf.cpp工具明确指出CONFIG_DEVMEM选项应该设置为n而不是y。
  • 查看内核的defconfig,发现根本没有设置这个选项,那就很奇怪了,最简单的操作是直接禁用这个选项,但是这个选项的的作用是访问物理地址而不是虚拟地址,禁用可能不便于调试,所以还是要看能不能绕过检测。

    为何CONFIG_DEVMEM没有在defconfig中使能,但是最终.config中是使能状态

  • 寻找这个选项
      find . -type f -name "*Kconfig*" | xargs grep -li "DEVMEM"
    
  • 输出如下
      ./lib/Kconfig.debug
      ./security/Kconfig
      ./drivers/char/Kconfig
      ./arch/s390/Kconfig
      ./arch/x86/Kconfig
      ./arch/powerpc/Kconfig
      ./arch/arm64/Kconfig
      ./arch/arm/Kconfig
    
  • kernel-5.10/drivers/char/Kconfig中,有对这个选项的定义
      config DEVMEM
          bool "/dev/mem virtual device support"
          default y
          help
          Say Y here if you want to support the /dev/mem device.
          The /dev/mem device is used to access areas of physical
          memory.
          When in doubt, say "Y".
    

    可以看到,如果没有显式设置,系统将默认启用这个选项。

如何绕过VINTF兼容性检测

上文提到,CONFIG_DEVMEM选项最好还是开着,方便访问物理内存,但是VINTF检测又会在选项开启的情况下导致编译失败,那么有没有方式绕过这种检测呢?

删除掉# CONFIG_DEVMEM is not set的原理

最重要的是下面这篇文章: https://android.googlesource.com/kernel/configs/+/bf200243937a80c3ab1f6664d0e7b3615ce25065/README.md

文章中提到了几个重要的点:

  1. android-base.config 是定义 Android 必需内核配置的片段文件
    • 原文:Kernel configuration settings that must be present for Android to function are located in the base config fragment, android-base.config.
  2. ​android-base.config 是构建最终 .config 的输入片段之一 (合并过程) alt text
  3. ​android-base.config 是生成 FCM (框架兼容性矩阵) 中内核配置要求的来源 alt text
  4. 修改 android-base.config 是允许的操作 (移除行) alt text

由文章可知:FCM中内核配置要求的来源之一是​android-base.config,类似于# CONFIG_DEVMEM is not set这样的注释行,会让FCM的内核配置要求生成有关CONFIG_DEVMEM选项检查的内容,而内核中默认使能了CONFIG_DEVMEM,就会导致检测不通过;而完全删除和CONFIG_DEVMEM有关的内容,可以避免生成CONFIG_DEVMEM选项检查的相关内容,从而绕过VINTF检测。

解决方式

diff --git a/kernel/configs/s/android-5.10/android-base.config b/kernel/configs/s/android-5.10/android-base.config
index d6e1f5a3a8..d7078da1bd 100755
--- a/kernel/configs/s/android-5.10/android-base.config
+++ b/kernel/configs/s/android-5.10/android-base.config
@@ -2,7 +2,6 @@
 # CONFIG_ANDROID_LOW_MEMORY_KILLER is not set
 # CONFIG_ANDROID_PARANOID_NETWORK is not set
 # CONFIG_BPFILTER is not set
-# CONFIG_DEVMEM is not set
 # CONFIG_FHANDLE is not set
 # CONFIG_FW_CACHE is not set
 # CONFIG_IP6_NF_NAT is not set

这个文件的位置我也验证了很久,因为实际上有多个android-base.config,如果你尝试在这个文件中更改不生效,可以试试看下面的位置:

./mkcombinedroot/configs/android-13.config

./kernel-5.10/kernel/configs/android-base.config

./kernel/configs/s/android-5.10/android-base.config

./kernel/configs/android-5.10/android-base.config

留下评论