文档内容拷贝自:
codebase_host/yunhal/opendoc/zh/porting_guide/kernel_porting.md
联系人:赤铁
版本: commit-id(b04553d1a2bd7b00e9120c7c1a98ae15a333cbe4
)
内核代码由芯片厂商随BSP
一起提供,厂商的BSP
现阶段一般是基于Android HAL
的,因此需要针对YunOS
系统进行必要的处理。我们首先需要将内核代码放入YunOS
编译体系,然后再针对YunHal
作一些必要的适配和移植。
在Host
侧为内核代码创建git
库,一般是vendor/xxx/linux/kernel_yunhal
目录。
kernel
纳入YunOS
编译体系:xmake/platform/<platform>/product/yunhal/xmake.product
--pkgs-included
中添加一项kernel_yunhal
。<platform>
根据平台不同,可以是phone
,tablet
,tv
等。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_yunhal
的make
指令时,会判断当前的平台名称是否是tablet
,如果是,则进入相应的目录调用相关的脚本进行kernel
的编译工作。在实际操作中可以根据自身的平台或产品名称进行判断。
更多的xmake
相关信息请参考xmake
的相关文档。
添加vendor/xxx/linux/kernel_yunhal/kernel_build.sh
,这个脚本被xmake编译系统调用,完成内核编译工作。
kernel_build.sh
开头是一些变量定义
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 clean
与Make 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
台为例进行介绍,如果不同平台还有其它特定的文件需要安装,或者配置一些环境, 也可以在这个脚本里添加相应的命令。
selinux
厂商提供的内核一般是使能SELinux
的,会给产品bringup
带来困难,由于后续使能安全特性时会使能AliSec
,所以先将内核的SELinux
特性关闭
CONFIG_SECURITY_SELINUX=n CONFIG_DEFAULT_SECURITY_SELINUX=n #CONFIG_DEFAULT_SECURITY="selinux"
adb -host
为了方便调试YunOS
,需要添加/dev/android_adb
设备以便YunOS
的adbd
与之交互。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 devices
及adb shell
进行察看和调试。
YunOS
采用KDBus
作为系统IPC
,较之传统的D-Bus
,更加安全和高效。在产品bringup
早期,YunOS
也支持打开D-Bus
开关进行工作,但到桌面可以显示后,还是要尽早切换到KDBus
开关,依赖KDBus
作为系统IPC
进行工作。厂商提供的内核是不包含KDBus
相关代码的,具体移植步骤请参考[KDBus移植文档]
YunOS
提供了丰富的特性来保证设备运行安全可靠,比如权限系统, AliSec
, Alitks
等等。这些安全特性的移植,请参考[系统安全移植文档]