文档中心 > 芯片厂商开放

内核移植

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

文档内容拷贝自: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文件:
    [[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

    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特性关闭

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设备节点。

--- 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
返回
顶部