Yocto开发相关笔记

  1. 添加一个新的machine

    添加一个新的machine需要在新加layer的conf/machine/目录中填写对应的配置文件,比如:raspberrypi3.conf是树莓派3的配置文件。该配置文件位于meta-raspberrypi/conf/machine/raspberrypi3.conf。

    machine的配置文件中一般都包含如下内容:

    TARGET_ARCH:指出目标平台架构名称,如:arm

    PREFERRED_PROVIDER:指出优先采用的recipe名称。比如:PREFERRED_PROVIDER_virtual/kernel ?= “linux-raspberry”,说明对于kernel的使用,优先采用linux-raspberrypi这个recipe。

    MACHINE_FEATURES:指出MACHINE支持的硬件特性,比如:MACHINE_FEATURES = “apm bluetooth wifi screen”

    SERIAL_CONSOLE:指出串口的配置,比如:SERIAL_CONSOLE = “115200 ttyS0”

    KERNEL_IMAGETYPE:指出linux内核镜像的类型,比如:KERNEL_IMAGETYPE = “zImage”

    IMAGE_FSTYPES:指出文件系统镜像的文件系统类型,比如:IMAGE_FSTYPES = “tar.gz jffs2”

  1. 配置linux内核

    使用menuconfig来配置内核。

        $bitbake linux-yocto -c kernel_configme -f

        $bitbake linux-yocto -c menuconfig

    创建defconfig文件来配置内核。

        defconfig文件就是kernel的.config文件的更名,将defconfig文件复制到recipe目录中,之后在.bb或.bbappend文件中添加如下内容:

            FILESEXTRAPATHS_prepend := “${THISDIR}/${PN}: “

            SRC_URI += “file://defconfig”

    创建配置分片(configuration fragments)

        可以将内核的配置项分散到多个配置文件中,之后将配置文件放置到recipe目录中,最后在.bb或.bbappend文件中添加如下内容:

            SRC_URI += “file://myconfig.cfg \

                        file://ethernet.cfg \

                        file://gfx.cfg”

        OpenEmbedded编译系统会逐个读取出这个分片的内容,之后添加到内核配置文件.config中。

    微调内核配置文件

        通过调用do_kernel_configme和do_kernel_configcheck任务来微调内核配置文件。

            $bitbake linux-yocto -c kernel_configme 

            $bitbake linux-yocto -c kernel_configcheck

        执行完kernel_configcheck后会输出一系列警告或问题,解决之。之后重新执行上述两个命令,直到满意为止。

  1. kernel打patch

    3.1 找到当前内核源代码路径,即:cd ~/poky/build/tmp/work/qemux86-poky-linux/linux-yocto-${PV}-${PR}/linux

    3.2 修改内核源代码文件。

    3.3 使用git命令提交修改后的内核源代码。

        $git status .

        $git add .

        $git commit -m “xxx”

    3.4 创建patch文件。

        $git format-path -1

    3.5 创建自己的layer。

        配置layer的conf目录和recipes-kernel/linux目录

        在recipes-kernel/linux目录下创建recipe文件,即:linux-yocto_${PV}.bbappend。之后在文件中添加如下内容:

            FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"

                 SRC_URI += "file://0001-calibrate-Add-printk-example.patch"

        在recipes-kernel/linux目录下创建linux-yocto目录,之后将内核patch文件复制到该目录中

    3.6 检查自己的layer的有效性。

        在build目录里的conf/bblayer.conf中查看自己的layer是否被添加到BBLAYER变量中

    3.7 重新编译内核。

        $bitbake -c cleansstate linux-yocto    清空缓存中的内容

        $bitbake -k linux-yocto            重新编译内核

  1. 安全问题

    4.1 安全问题的总体考虑。

        使用静态分析工具扫描添加到系统中的其它代码;

        格外注意基于web的管理员接口;

        确保软件的及时更新;

        发布版本的时候确保删除或禁用debug功能;

        确保发行版本中不会有不需要的网络监听程序;

        删除发行版中不必要的软件;

        确认硬件上支持secure boot功能;

    4.2 Security flags。

        若需要Security的编译,则需要在local.conf中添加如下一行:

            require conf/distro/include/security_flags.inc

        security_flags.inc文件中主要是包含了编译/链接过程中的关于安全的相关选项。

    4.3 其它的考虑。

        在image中去掉IMAGE_FEATURES或EXTRA_IMAGE_FEATURES=“debug-tweaks”选项

        使用extrausers类实现root用户以及其它用户的密码设置

        考虑使用Mandatory Access Control(MAC),即:使用meta-selinux层

        考虑使用meta-security层

  1. Packages相关操作

    5.1 制作镜像的时候删除包。

        使用如下变量实现:

            BAD_RECOMMENDATIONS:该变量针对recommended-only包有效;

            NO_RECOMMENDATIONS:该变量用于禁止安装所有recommend-only包;

            PACKAGE_EXCLUDE:该变量用于禁止指定包的安装;

    5.2 制作运行时动态安装包。

        在源代码包编译的过程中需要在变量IMAGE_FEATURES中添加package-management;

        在服务器端需要添加http等服务;

  1. Initialization Manager的选择

    yocto默认使用SysVinit作为启动器,然而yocto也支持systemd启动方式。若选择systemd则需要如下内容:

    设置如下变量启用systemd:

        DISTRO_FEATURES_append = “ systemd”

        VIRTUAL-RUNTIME_init_manager = “systemd”

    此时系统启动的时候默认采用systemd方式启动,但是sysvinit脚本也安装到image中只不过在rescure/minimal中使用sysvinit方式启动

    删除SysVinit脚本:

        DISTRO_FEATURES_BACKFILL_CONSIDERED = “sysvinit”

  1. 选择一个设备管理器

    设备管理器用于管理/dev目录,设备管理器包括:静态的和动态的。其中静态的在编译过程中确定/dev目录中的内容,之后就不再变化了,而动态的则是实用devtmpfs来管理/dev目录,由内核在启动过程中动态的操作且在用户态空间由udev或者busybox-mdev进程进行处理。

    静态管理:

        设置USE_DEVFS = “0”

        设置IMAGE_DEVICE_TABLES = “device_table_mymachine.txt”设置device tables文件

    动态管理:

        设置USE_DEVFS = “1”。此时内核采用devtmpfs来初始化/dev目录(在内核配置方面要添加CONFIG_DEVTMPFS);

        所有由devtmpfs创建的设备节点属于root用户且访问权限是0600;

        设置用户态设备管理进程,即:VIRTUAL-RUNTIME_dev_manager = “udev” 设置设备管理用户态进程为udev;