文档中心 > 芯片厂商开放

内核移植

更新时间:2017/08/17 访问次数:2611

文档内容拷贝自:codebase_host/yunhal/opendoc/zh/porting_guide/kernel_porting.md
联系人:赤铁
版本: commit-id(b04553d1a2bd7b00e9120c7c1a98ae15a333cbe4)

前言

内核代码由芯片厂商随BSP一起提供,厂商的BSP现阶段一般是基于Android HAL的,因此需要针对YunOS系统进行必要的处理。我们首先需要将内核代码放入YunOS编译体系,然后再针对YunHal作一些必要的适配和移植。

1. 创建git库

Host侧为内核代码创建git库,一般是vendor/xxx/linux/kernel_yunhal目录。

2. 编译内核

2.1 将kernel纳入YunOS编译体系:

  • 修改xmake/platform/<platform>/product/yunhal/xmake.product
    --pkgs-included中添加一项kernel_yunhal
    其中<platform>根据平台不同,可以是phonetablettv等。
  • 添加xmake/confs.3/kernel_yunhal/xmake.conf文件:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    [[yunos_root]]/vendor/intel/linux/kernel_yunhal
    --disable-configure
    --make \
            echo "platform-name = x[[platform-name]] product-name = x[[product-name]]" ; \
            if [ x"[[platform-name]]" = x"tablet" ]; then \
                    cd [[yunos_root]]/vendor/intel/linux/kernel_yunhal/; \
                    product="tablet_cht"; \
                    product_variant="cht"; \
                    if [ ! -x "kernel_build.sh" ]; then \
                            chmod a+x ./kernel_build.sh; \
                    fi; \
                    TOP_DIR=[[yunos_root]] PROD_MODE=[[XMAKE_PROD_MODE]] SECURE_BOOT_ENABLE=[[XMAKE_PROD_MODE]] ./kernel_build.sh $${product} $${product_variant} new $${XMAKE_BUILD_TYPE} ; \
                    if [ "$$?" -ne 0 ]; then echo "Building kernel Error ..... !!!!"; exit 1; fi; \
                    cd -; \
                    exit 0; \
            fi
    --make-install \
            echo "fake make install"
    --make-clean \
            echo "ignore"
    --make-distclean \
            echo "ignore"

    在上述例子中,/vendor/intel/linux/kernel_yunhal对应前述创建的git库目录,xmake在执行添加项kernel_yunhalmake指令时,会判断当前的平台名称是否是tablet,如果是,则进入相应的目录调用相关的脚本进行kernel的编译工作。在实际操作中可以根据自身的平台或产品名称进行判断。

更多的xmake相关信息请参考xmake的相关文档。

2.2 编写编译脚本

添加vendor/xxx/linux/kernel_yunhal/kernel_build.sh,这个脚本被xmake编译系统调用,完成内核编译工作。

  • kernel_build.sh开头是一些变量定义

    !/bin/bash

    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
    set -x                          #help to debug
    set -e                          #exit when error
    TARGET_PRODUCT=$1               # tablet_cht
    PRODUCT_VARIANT=$2              # cht
    BUILD_MODE_VARIANT=$3           # new/remake
    BUILD_TYPE_VARIANT=$4           # eng/user
    PRODUCT_IMG_DIR="${TOP_DIR}/prebuilts/images/${TARGET_PRODUCT}"  #image output dir
     
    CPU_NUM=`nproc --all`
     
    MAKE="make -j${CPU_NUM} SHELL=/bin/bash"
    PWD=`pwd`
     
    KERNEL_ARCH="x86_64"            # arm/arm64
    KERNEL_CROSS_COMP="x86_64-poky-linux-"
     
    KERNEL_OUT_DIR="../out/kernel"      # .o files output dir
    KERNEL_MODINSTALL="modules_install"
    KERNEL_OUT_MODINSTALL="../out/${KERNEL_MODINSTALL}"  # .ko files output dir
    KERNEL_MODULES_ROOT="${buildroot}/${_libdir}/modules" # .ko files install dir
    KERNEL_CONFIG="${KERNEL_OUT_DIR}/.config"
    KERNEL_EXTRA_FLAGS=""
    KERNEL_BLD_FLAGS="ARCH=${KERNEL_ARCH} INSTALL_MOD_PATH=../${KERNEL_MODINSTALL} TARGET_PRODUCT=${TARGET_PRODUCT} TARGET_BUILD_VARIANT=${BUILD_TYPE_VARIANT} YUNOS_WITH_BOARD=${TARGET_PRODUCT}"
     
    KERNEL_BLD_FLAGS="${KERNEL_BLD_FLAGS} O=${KERNEL_OUT_DIR}" # build flags
     
    KERNEL_BLD_ENV="CROSS_COMPILE=${KERNEL_CROSS_COMP}"
    KERNEL_FAKE_DEPMOD="${KERNEL_OUT_DIR}/fakedepmod/lib/modules"
     
    KERNEL_SRC_DIR="${PWD}"
    KERNEL_VERSION_FILE="${KERNEL_OUT_DIR}/include/config/kernel.release"
    KERNEL_BZIMAGE="${PRODUCT_IMG_DIR}/kernel"
     
    CPUCORES=`cat /proc/cpuinfo |grep processor|wc -l`
  • 清理上次编译生成的.o文件,并重新创建生成.o 文件所需的目录

    rm -rf ../out
    mkdir -p ${KERNEL_OUT_DIR}

  • 安装工具链

    echo “Installing toolchain”
    TOOLCHAIN_DIR=${TOP_DIR}/vendor/intel/linux/toolchain
    export PATH=${TOOLCHAIN_DIR}/sysroots/x86_64-pokysdk-linux/usr/bin/x86_64-poky-linux:$PATH
    export ${KERNEL_BLD_ENV}
    echo “TOOLCHAIN_DIR = ${TOOLCHAIN_DIR}”

  • 创建到YunOS独有代码的符号连接

    echo “Create link to yunos module codes”
    ln -sf ${TOP_DIR}/security/extern/gpl/yunos ${KERNEL_SRC_DIR}/
    echo “Create link to kdbus codes”
    ln -sf ${TOP_DIR}/security/extern/gpl/kernel/include/uapi/linux/kdbus.h ${KERNEL_SRC_DIR}/include/uapi/linux/
    ln -sf ${TOP_DIR}/security/extern/gpl/kernel/ipc/kdbus ${KERNEL_SRC_DIR}/ipc/

  • Make cleanMake config

    #Clean kernel
    ${MAKE} mrproper

    #Make config
    KERNEL_DEFCONFIG=“x86_64_defconfig” # Modify this according to your kernel
    if [ “$BUILD_TYPE_VARIANT”x == “user”x ]; then
    if [ “$PROD_MODE”x == “on”x ]; then
    KERNEL_DEFCONFIG=“x86_64_release_defconfig”
    else
    KERNEL_DEFCONFIG=“x86_64_user_defconfig”
    fi
    fi
    echo “KERNEL_DEFCONFIG:$KERNEL_DEFCONFIG”
    echo “BUILD_TYPE_VARIANT:$BUILD_TYPE_VARIANT”
    ${MAKE} -C ${KERNEL_SRC_DIR} ${KERNEL_BLD_FLAGS} $KERNEL_DEFCONFIG
    [ $? -ne 0 ] && echo “make x86_64_defconfig” && exit 1

  • 编译内核和模块

    #Build vmlinux
    ${MAKE} -C ${KERNEL_SRC_DIR} ${KERNEL_BLD_FLAGS} ${KERNEL_EXTRA_FLAGS} -j${CPUCORES} V=1
    cp -f ${KERNEL_OUT_DIR}/vmlinux ${PRODUCT_IMG_DIR}

    #Build bzImage
    ${MAKE} -C ${KERNEL_SRC_DIR} ${KERNEL_BLD_FLAGS} ${KERNEL_EXTRA_FLAGS} -j${CPUCORES} bzImage V=1
    [ $? -ne 0 ] && echo “make bzImage failed” && exit 1
    cp -f ${KERNEL_OUT_DIR}/arch/x86/boot/bzImage ${KERNEL_BZIMAGE}

    #Build modules
    mkdir -p ${buildroot}/etc/modules-load.d/
    mkdir -p ${buildroot}/etc/modprobe.d/
    mkdir -p ${KERNEL_OUT_MODINSTALL}
    ${MAKE} -C ${KERNEL_SRC_DIR} ${KERNEL_BLD_FLAGS} modules
    [ $? -ne 0 ] && echo “make modules failed” && exit 1
    ${MAKE} -C ${KERNEL_SRC_DIR} ${KERNEL_BLD_FLAGS} modules_install
    [ $? -ne 0 ] && echo “make modules_install failed” && exit 1

    mkdir -p ${KERNEL_OUT_DIR}/bluetooth
    ${MAKE} -C ${KERNEL_SRC_DIR}/../modules/bluetooth/cht/ ${KERNEL_BLD_FLAGS} KLIB_BUILD=${KERNEL_SRC_DIR}/../out/kernel/ CCACHE_SLOPPINESS= defconfig-bluetooth
    ${MAKE} -C ${KERNEL_SRC_DIR}/../modules/bluetooth/cht/ ${KERNEL_BLD_FLAGS} KLIB_BUILD=${KERNEL_SRC_DIR}/../out/kernel/ CCACHE_SLOPPINESS= modules
    ${MAKE} -C ${KERNEL_SRC_DIR}/../modules/bluetooth/cht/ ${KERNEL_BLD_FLAGS} KLIB_BUILD=${KERNEL_SRC_DIR}/../out/kernel/ CCACHE_SLOPPINESS= modules_install

可能不同产品还需要额外编译其它的module,可参考bluetooth module自行添加。

  • 安装模块并签名

    #copy_modules_to_root
    rm -rf ${KERNEL_MODULES_ROOT}
    mkdir -p ${KERNEL_MODULES_ROOT}
    cp -a ${KERNEL_OUT_MODINSTALL}/lib/modules/* ${KERNEL_MODULES_ROOT}
    find ${KERNEL_MODULES_ROOT} -name "*.ko" -exec ${KERNEL_SRC_DIR}/scripts/sign-file sha512 ${KERNEL_SRC_DIR}/../out/kernel/signing_key.priv ${KERNEL_SRC_DIR}/../out/kernel/signing_key.x509 {} \;
    /sbin/depmod -b ${buildroot} cat ${KERNEL_VERSION_FILE}

以上是以PAD台为例进行介绍,如果不同平台还有其它特定的文件需要安装,或者配置一些环境, 也可以在这个脚本里添加相应的命令。

3. 关闭selinux

厂商提供的内核一般是使能SELinux的,会给产品bringup带来困难,由于后续使能安全特性时会使能AliSec,所以先将内核的SELinux特性关闭

1
2
3
CONFIG_SECURITY_SELINUX=n
CONFIG_DEFAULT_SECURITY_SELINUX=n
#CONFIG_DEFAULT_SECURITY="selinux"

4. 使能adb -host

为了方便调试YunOS,需要添加/dev/android_adb设备以便YunOSadbd与之交互。adb usb驱动的实现目前主要有两种方式:一种是在内核空间通过usb gadget实现,另一种是在用户空间通过ffs实现。在kernel4.4及以上版本,只支持ffs方案,故无需修改kernel,只需要在用户空间配置设备节点并挂载configfs/functionfs

对于kernel4.4以下的版本,需要修改usb驱动,创建/dev/android_adb设备节点。

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -48,6 +48,11 @@
 #include "rndis.c"
 #include "u_ether.c"
 
+/* YUNOS BEGIN */
+//##[BugID:11339403](add /dev/android_adb supported)
+#include "f_adb.c"
+/*??YUNOS END */
+
 MODULE_AUTHOR("Mike Lockwood");
 MODULE_DESCRIPTION("Android Composite USB Driver");
 MODULE_LICENSE("GPL");
@@ -382,6 +387,116 @@ static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
 {
 }
 
+/* YUNOS BEGIN */
+//##[BugID:11339403](add /dev/android_adb supported)
+#if 1
+struct adb_data {
+       bool opened;
+       bool enabled;
+};
+
+static int
+adb_function_init(struct android_usb_function *f,
+               struct usb_composite_dev *cdev)
+{
+       f->config = kzalloc(sizeof(struct adb_data), GFP_KERNEL);
+       if (!f->config)
+               return -ENOMEM;
+
+       return adb_setup();
+}
+
+static void adb_function_cleanup(struct android_usb_function *f)
+{
+       adb_cleanup();
+       kfree(f->config);
+}
+
+static int
+adb_function_bind_config(struct android_usb_function *f,
+               struct usb_configuration *c)
+{
+       return adb_bind_config(c);
+}
+
+static void adb_android_function_enable(struct android_usb_function *f)
+{
+/* This patch cause WHQL fail */
+#if 0
+       struct android_dev *dev = _android_dev;
+       struct adb_data *data = f->config;
+
+       data->enabled = true;
+
+       /* Disable the gadget until adbd is ready */
+       if (!data->opened)
+               android_disable(dev);
+#endif
+}
+
+static void adb_android_function_disable(struct android_usb_function *f)
+{
+/* This patch cause WHQL fail */
+#if 0
+       struct android_dev *dev = _android_dev;
+       struct adb_data *data = f->config;
+
+       data->enabled = false;
+
+       /* Balance the disable that was called in closed_callback */
+       if (!data->opened)
+               android_enable(dev);
+#endif
+}
+
+static struct android_usb_function adb_function = {
+       .name           = "adb",
+       .enable         = adb_android_function_enable,
+       .disable        = adb_android_function_disable,
+       .init           = adb_function_init,
+       .cleanup        = adb_function_cleanup,
+       .bind_config    = adb_function_bind_config,
+};
+
+static void adb_ready_callback(void)
+{
+/* This patch cause WHQL fail */
+#if 0
+       struct android_dev *dev = _android_dev;
+       struct adb_data *data = adb_function.config;
+
+       mutex_lock(&dev->mutex);
+
+       data->opened = true;
+
+       if (data->enabled)
+               android_enable(dev);
+
+       mutex_unlock(&dev->mutex);
+#endif
+}
+
+static void adb_closed_callback(void)
+{
+/* This patch cause WHQL fail */
+#if 0
+       struct android_dev *dev = _android_dev;
+       struct adb_data *data = adb_function.config;
+
+       mutex_lock(&dev->mutex);
+
+       data->opened = false;
+
+       if (data->enabled)
+               android_disable(dev);
+
+       mutex_unlock(&dev->mutex);
+#endif
+}
+#endif
+/* YUNOS END */
+
+
 #define MAX_ACM_INSTANCES 4
 struct acm_function_config {
        int instances;
@@ -1219,6 +1334,10 @@ static struct android_usb_function midi_function = {
 #endif
 static struct android_usb_function *supported_functions[] = {
        &ffs_function,
+       /* YUNOS BEGIN */
+       //##[BugID:11339403](add /dev/android_adb supported)
+       &adb_function,
+       /* YUNOS END */
        &mtp_function,
        &ptp_function,
        &rndis_function,
@@ -1416,6 +1535,16 @@ functions_store(struct device *pdev, struct device_attribute *attr,
                }
 
                if (is_ffs) {
+                       /* YUNOS BEGIN */
+                       //##[BugID:11339403](add /dev/android_adb supported)
+                       if (!strcmp(name, "adb")) {
+                               pr_info("android_usb:enable adb driver\n");
+                               err = android_enable_function(dev, name);
+                               if (err)
+                                       pr_err("android_usb: Cannot enable '%s' (%d)\n",
+                                               name, err);
+                       }
+                       /* YUNOS END */
                        if (ffs_enabled)
                                continue;
                        err = android_enable_function(dev, "ffs");
 
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -63,7 +63,7 @@ static struct usb_interface_descriptor adb_interface_desc = {
        .bInterfaceNumber       = 0,
        .bNumEndpoints          = 2,
        .bInterfaceClass        = 0xFF,
-       .bInterfaceSubClass     = 0x42,
+       .bInterfaceSubClass     = 0xa2,
        .bInterfaceProtocol     = 1,
 };

在使能通过后即可以通过adb -host devices列出YunOS``Host设备,并利用指令adb -host shell连接到设备上进行调试,而Guest设备仍然可以通过adb devicesadb shell进行察看和调试。

5. 使能KDBUS

YunOS采用KDBus作为系统IPC,较之传统的D-Bus,更加安全和高效。在产品bringup早期,YunOS也支持打开D-Bus开关进行工作,但到桌面可以显示后,还是要尽早切换到KDBus开关,依赖KDBus作为系统IPC进行工作。厂商提供的内核是不包含KDBus相关代码的,具体移植步骤请参考[KDBus移植文档]

6. 使能安全特性

YunOS提供了丰富的特性来保证设备运行安全可靠,比如权限系统, AliSecAlitks等等。这些安全特性的移植,请参考[系统安全移植文档]

FAQ

关于此文档暂时还没有FAQ
返回
顶部