官方的文档我觉得是最终的产品形态,一个新品在开发移植过程中不太可能一步到位,尤其是非官方支持版本,所以多少还是要拆分下。

准备整体构建环境

1 准备代码

理论上path不是问题,只要找到就好。这里就把要用的三方内核,比如我的是Linux-5.4就放到Linux目录下。

tj@ubuntu:~/code/oh-3.2.2/kernel/linux$ ls
build  config  linux-5.10  linux-5.4  patches  third_party  vendor

2 配置ARM64编译环境

check build/kernel.mk:

 31 CLANG_HOST_TOOLCHAIN := $(OHOS_BUILD_HOME)/prebuilts/clang/ohos/linux-x86_64/llvm/bin
 32 KERNEL_HOSTCC := $(CLANG_HOST_TOOLCHAIN)/clang
 33 KERNEL_PREBUILT_MAKE := make
 34 CLANG_CC := $(CLANG_HOST_TOOLCHAIN)/clang
 39 else ifeq ($(KERNEL_ARCH), arm64)
 40     KERNEL_TARGET_TOOLCHAIN := $(PREBUILTS_GCC_DIR)/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin
 41     KERNEL_TARGET_TOOLCHAIN_PREFIX := $(KERNEL_TARGET_TOOLCHAIN)/aarch64-linux-gnu-

进入Linux-5.4:

export PATH=./../../prebuilts/clang/ohos/linux-x86_64/llvm/bin:./../../prebuilts/gcc/linux-x86/aarch64/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/:$PATH
export MAKE_OPTIONS="ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- CC=clang HOSTCC=clang"

3 编译Image和模块

移植前先编译一次三方内核,确保无误。

make $MAKE_OPTIONS O=out/ -j4
make $MAKE_OPTIONS O=out/ -j4 modules

移植内核态基础代码

官方文档提到的hilog/hievent:

drivers/staging/hilog
drivers/staging/hievent

还有这几个特性:

drivers/staging/hisysevent
drivers/staging/hungtask
drivers/staging/zerohung
drivers/staging/blackbox

对应的头文件:

include/dfx/hiview_hisysevent.h               |   67 ++
include/dfx/hung_wp_screen.h                  |   24 +
include/dfx/hungtask_base.h                   |  111 ++
include/dfx/zrhung.h                          |   11 +
include/linux/blackbox.h                      |   84 ++
include/linux/blackbox_common.h               |   44 +
include/linux/blackbox_storage.h              |   22 +

drivers下还有个accesstokenid特性,改的地方还不只一处:

tj@ubuntu:~/ohos-3.2.2/kernel/linux/linux-5.10$ grep -R ACCESS_TOKENID --exclude-dir=accesstokenid
include/linux/sched.h:#ifdef CONFIG_ACCESS_TOKENID
drivers/Makefile:obj-$(CONFIG_ACCESS_TOKENID)   += accesstokenid/
drivers/android/binder.c:#ifdef CONFIG_ACCESS_TOKENID
drivers/android/binder.c:#define ENABLE_ACCESS_TOKENID 1
drivers/android/binder.c:#define ENABLE_ACCESS_TOKENID 0
drivers/android/binder.c:#endif /* CONFIG_ACCESS_TOKENID */
drivers/android/binder.c:#define ACCESS_TOKENID_FEATURE_VALUE (ENABLE_ACCESS_TOKENID << 0)
drivers/android/binder.c:#define BINDER_CURRENT_FEATURE_SET ACCESS_TOKENID_FEATURE_VALUE
drivers/android/binder.c:#ifdef CONFIG_ACCESS_TOKENID
drivers/android/binder.c:#endif /* CONFIG_ACCESS_TOKENID */
drivers/android/binder.c:#ifdef CONFIG_ACCESS_TOKENID
drivers/android/binder.c:#endif /* CONFIG_ACCESS_TOKENID */
drivers/android/binder.c:#ifdef CONFIG_ACCESS_TOKENID
drivers/android/binder.c:#endif /* CONFIG_ACCESS_TOKENID */
drivers/android/binder.c:#ifdef CONFIG_ACCESS_TOKENID
drivers/android/binder.c:#endif /* CONFIG_ACCESS_TOKENID */
drivers/android/binder.c:#ifdef CONFIG_ACCESS_TOKENID
drivers/android/binder.c:#endif /* CONFIG_ACCESS_TOKENID */
fs/proc/base.c:#ifdef CONFIG_ACCESS_TOKENID
fs/proc/base.c:#endif /* CONFIG_ACCESS_TOKENID */
fs/proc/base.c:#ifdef CONFIG_ACCESS_TOKENID
fs/proc/base.c:#ifdef CONFIG_ACCESS_TOKENID
kernel/fork.c:#ifdef CONFIG_ACCESS_TOKENID

看了下 caller path:

base/security/access_token

所以说,要拿一个非官方支持的内核版本落地产品,不是说不能做,还是要考虑清楚。

移植内核态必选特性HDF

官方的打hdf patch方法, 看kernel.mk:

 83         $(hide) $(OHOS_BUILD_HOME)/drivers/hdf_core/adapter/khdf/linux/patch_hdf.sh $(OHOS_BUILD_HOME) $(KERNEL_SRC_TMP_PATH) $(KERNEL_PATCH_PATH) $(DEVICE_NAME)

patch_hdf.sh:

 65 function main()
 66 {
 67     cd $KERNEL_BUILD_ROOT
 68     put_hdf_patch
 69     ln_hdf_repos
 70     copy_external_compents
 71     cd -
 72 }

put_hdf_patch:

 55 function put_hdf_patch()
 56 {
 57     HDF_PATCH_FILE=${KERNEL_PATCH_PATH}/${DEVICE_NAME}_patch/hdf.patch
 58     if [ ! -e "${HDF_PATCH_FILE}" ]
 59     then
 60             HDF_PATCH_FILE=${KERNEL_PATCH_PATH}/${HDF_COMMON_PATCH}_patch/hdf.patch
 61     fi
 62     patch -p1 < $HDF_PATCH_FILE
 63 }

我们这里用的是60行通用的hdf.patch:

kernel/linux/patches/linux-5.10/common_patch/hdf.patch

这个patch是给5.10用,我们是5.4,直接打多少应该是有问题的,还好只有300多行,手动改改即可。

然后,注掉这个put_hdf_patch, 跑下patch_hdf.sh即可, 多了个PRODUCT_PATH:

export PRODUCT_PATH=vendor/$your_product

使能几个,最大的问题就是有很多下面这类错误:

../drivers/hdf/khdf/manager/../../../..//framework/core/host/src/hdf_device_node.c:156:27: error: ISO C90 forbids mixing declarations and code [-Werror,-Wdeclaration-after-statement]
    struct HdfServiceInfo servInfo;

code是这样写的:

149 int HdfDeviceNodePublishPublicService(struct HdfDeviceNode *devNode)
150 {
151     int ret;
152     if (devNode == NULL || devNode->deviceObject.service == NULL) {
153         HDF_LOGE("failed to publish public service, devNode is NULL");
154         return HDF_FAILURE;
155     }
156     struct HdfServiceInfo servInfo;
157     HdfServiceInfoInit(&servInfo, devNode);
158     ret = DevSvcManagerClntAddService(&devNode->deviceObject, &servInfo);
159     if (ret == HDF_SUCCESS) {
160         devNode->servStatus = true;
161     }
162 

C90不允许declaration-after-statement,看了下5.4/5.10还是gnu89, 上游已经更新到gnu11了,照样改过来fix即可。

整个移植下来的感觉就是你可以把它当成个黑盒,不需要有太多的Linux Kernel背景。

参考