文档内容拷贝自:
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等等。这些安全特性的移植,请参考[系统安全移植文档]