文档内容拷贝自:
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
文件: 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_yunhal
的make
指令时,会判断当前的平台名称是否是tablet
,如果是,则进入相应的目录调用相关的脚本进行kernel
的编译工作。在实际操作中可以根据自身的平台或产品名称进行判断。
更多的xmake
相关信息请参考xmake
的相关文档。
添加vendor/xxx/linux/kernel_yunhal/kernel_build.sh
,这个脚本被xmake编译系统调用,完成内核编译工作。
kernel_build.sh
开头是一些变量定义
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 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
特性关闭
1 2 3 | 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
设备节点。
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 devices
及adb shell
进行察看和调试。
YunOS
采用KDBus
作为系统IPC
,较之传统的D-Bus
,更加安全和高效。在产品bringup
早期,YunOS
也支持打开D-Bus
开关进行工作,但到桌面可以显示后,还是要尽早切换到KDBus
开关,依赖KDBus
作为系统IPC
进行工作。厂商提供的内核是不包含KDBus
相关代码的,具体移植步骤请参考[KDBus移植文档]
YunOS
提供了丰富的特性来保证设备运行安全可靠,比如权限系统, AliSec
, Alitks
等等。这些安全特性的移植,请参考[系统安全移植文档]