赞
踩
在进行OpenBMC开发之前首先需要对OpenBMC的代码框架做简单的介绍。
OpenBMC是基于OpenEmbeded(后面简称OE)这个开源框架的,该框架提供的了一系列的工具(最重要的是bitbake)以及一系列的文件。这些文件包括配置、配方等等。每个配方对应一个特定的实现,比如它可以描述一个程序(比如Linux、gcc等等)从代码获取、打补丁、配置、编译、安装等所有操作;而配置文件组合所有需要的程序,最终通过bitbake工具打包成一个Linux系统。
从这里也可以看出来,OE就是为了方便开发Linux系统,而不需要程序员再去关注各种细节,比如不同硬件平台的交叉编译之类的(这些都可以找到开源的配方来解决)。关于OE的进一步介绍,可以参考【Yocto】OpenEmbedded简介。
OpenBMC也是一个嵌入式的Linux,所以很自然地就可以引入OE这套系统,只是增加了BMC相关的驱动和应用如而已。
在【BMC】OpenBMC使用基础(WSL2版本)中直接使用了evb-ast2500这个原本就有的平台,而实际使用时最好是创建自己的项目,本节就是要创建自己的项目来构建OpenBMC。当在OE中新的项目时,实际上是创建一个称为Layer的目录。Layer将系统中的不同组件进行了逻辑上的分层,比如系统可以分层为BSP层、GUI层、中间件层、应用层,等等。这样一个Layer的修改不会也不应该影响到其它的Layer,方便更好地开发和维护OE项目。所以我们创建Layer(获取项目)的时候,实际上就是创建了一个自己用的分层,这里我们会放置我们自己的程序。
jw@HOME:~/openbmc$ . oe-init-build-env ### Shell environment set up for builds. ### You can now run 'bitbake <target>' Common targets are: core-image-minimal core-image-full-cmdline core-image-sato core-image-weston meta-toolchain meta-ide-support You can also run generated qemu images with a command like 'runqemu qemux86-64'. Other commonly useful commands are: - 'devtool' and 'recipetool' handle common recipe tasks - 'bitbake-layers' handles common layer tasks - 'oe-pkgdata-util' handles common target package tasks jw@HOME:~/openbmc/build$
setup脚本中实际上也是调用了oe-init-build-env而已:
if [ -n "$target" ]; then if [ "${name}" = "${target}" ]; then echo "Machine ${target} found in ${tmpl%/conf}" mkdir -p "${build_dir}" # 这里就执行了oe-init-build-env TEMPLATECONF="${tmpl}/templates/default" source \ oe-init-build-env "${build_dir}" if [ "$(cat conf/templateconf.cfg)" = "${tmpl}/templates/default" ]; then sed "s/^\(MACHINE\s*[?:]*\s*=\s*\).*$/\1\"${target}\"/" \ -i conf/local.conf fi return fi else echo "${name}" fi
从oe-init-build-env的打印可以看到可以使用bitbake-layers命令了,我们用它来创建自定义的项目(按照OE的说法是Layer),执行的命令如下:
jw@HOME:~/openbmc/build$ bitbake-layers create-layer ../meta-beni
NOTE: Starting bitbake server...
Add your new layer with 'bitbake-layers add-layer ../meta-beni'
jw@HOME:~/openbmc/build$
这样就可以在OpenBMC的根目录创建名为meta-beni的项目:
jw@HOME:~/openbmc/build$ tree ../meta-beni/
../meta-beni/
├── COPYING.MIT
├── README
├── conf
│ └── layer.conf
└── recipes-example
└── example
└── example_0.1.bb
3 directories, 4 files
jw@HOME:~/openbmc/build$
这里需要关注的就是一个layer.conf文件,它描述了我们自己的分层,其内容如下:
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-beni"
BBFILE_PATTERN_meta-beni = "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-beni = "6"
LAYERDEPENDS_meta-beni = "core"
LAYERSERIES_COMPAT_meta-beni = "mickledore"
这里比较重要的是值有两个(关于各类变量的描述,可以在5 Variables Glossary — Bitbake dev documentation (yoctoproject.org)找到):
BBPATH
:关于它的说明如下:Used by BitBake to locate class (
.bbclass
) and configuration (.conf
) files. This variable is analogous to thePATH
variable.If you run BitBake from a directory outside of the build directory, you must be sure to set BBPATH to point to the build directory.
它的值一般就是build目录:
jw@HOME:~/openbmc/build$ echo $BBPATH
/home/jw/openbmc/build
BBFILES
:关于它的说明如下:A space-separated list of recipe files BitBake uses to build software.
其它参数主要就是描述信息而已。
除了layer.conf之外的文件现在并没有什么用,因为要能够编译OpenBMC,还需要满足一些要求,所以需要一些额外的配方和配置文件。这里最简单的方法就是参考其它的项目,比如之前编译的OpenBMC来自meta-evb/meta-evb-aspeed/meta-evb-ast2500,这里直接拷贝它的配置文件,主要是machine和templates两个目录,且其中有一部分内容需要修改。之后还需要把webui-vue的配置也拿过来:
jw@HOME:~/openbmc/build$ tree ../meta-beni/ ../meta-beni/ ├── COPYING.MIT ├── README ├── conf │ ├── layer.conf │ ├── machine │ │ └── beni-ast2500.conf │ └── templates │ └── default │ ├── bblayers.conf.sample │ ├── conf-notes.txt │ └── local.conf.sample ├── recipes-example │ └── example │ └── example_0.1.bb └── recipes-phosphor └── packagegroups └── packagegroup-obmc-apps.bbappend 8 directories, 9 files jw@HOME:~/openbmc/build$
对应的代码已经上传https://gitee.com/jiangwei0512/meta-beni.git。这里存在两个目录:
machine
目录:它是setup脚本查找可构建项目的必要目录,事实上当我们执行. setup
时显示的命名就来自下面的conf文件的名称。beni-ast2500.conf的内容如下:KERNEL_DEVICETREE = "aspeed-ast2500-evb.dtb"
UBOOT_MACHINE = "evb-ast2500_defconfig"
UBOOT_DEVICETREE = "ast2500-evb"
require conf/machine/include/ast2500.inc
require conf/machine/include/obmc-evb-common.inc
SERIAL_CONSOLES = "115200;ttyS4"
FLASH_SIZE = "32768"
这个文件定义了大量的变量(其中一大部分是通过require引入的inc文件中定义的),它们最终描述了底层硬件,本例中就是ast2500芯片。需要注意的是,require的时候包含的inc文件使用的是相对路径,所以存在同名的情况,这个时候就需要依赖于bblayers.conf中定义的绝对路径,两者合起来就能够确定具体需要引入的是哪个文件。
templates
目录:从命名上看也能得出来,它里面包含的是一些目录文件,在setup脚本执行之后,文件内容会被稍加修改,并放到build/conf目录下,作为真正的配置文件,比如里面的bblayers.conf.sample文件:# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf # changes incompatibly LCONF_VERSION = "8" BBPATH = "${TOPDIR}" BBFILES ?= "" BBLAYERS ?= " \ ##OEROOT##/meta \ ##OEROOT##/meta-poky \ ##OEROOT##/meta-openembedded/meta-oe \ ##OEROOT##/meta-openembedded/meta-networking \ ##OEROOT##/meta-openembedded/meta-python \ ##OEROOT##/meta-phosphor \ ##OEROOT##/meta-aspeed \ ##OEROOT##/meta-beni \ "
到了build/conf目录下就变成了bblayers.conf:
# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf # changes incompatibly LCONF_VERSION = "8" BBPATH = "${TOPDIR}" BBFILES ?= "" BBLAYERS ?= " \ /home/jw/openbmc/meta \ /home/jw/openbmc/meta-poky \ /home/jw/openbmc/meta-openembedded/meta-oe \ /home/jw/openbmc/meta-openembedded/meta-networking \ /home/jw/openbmc/meta-openembedded/meta-python \ /home/jw/openbmc/meta-phosphor \ /home/jw/openbmc/meta-aspeed \ /home/jw/openbmc/meta-beni \ "
##OEROOT##
变成了实际的绝对路径。还要注意这里也有BBPATH
和BBFILES
,它会替换前面提到的beni-ast2500.conf中的值。
conf-notes.txt中的内容会在执行setup之后打印出来,告知可通过bitbake构建的二进制。
local.conf.sample里面也定义了一系列的变量,并会直接变成build/conf目录下的local.conf,内容不会发生变化。
上述的conf文件,最终就是定义了路径和一大堆的变量。路径比较好理解,就是用来定位文件;变量到后续使用到的时候再分析。
jw@HOME:~/openbmc$ . setup
Target machine must be specified. Use one of:
ahe50dc gsj s2600wf
beni-ast2500 kudo s6q
# 后面略
这里多了一个beni-ast2500(对应meta-beni/conf/machine/beni-ast2500.conf),就是我们自己的项目。后续执行:
. setup beni-ast2500 build
此时meta-beni/conf/templates/下的配置文件会被稍加修改之后放到build/conf目录下,作为全局的配置。
jw@HOME:~/openbmc/build/tmp/deploy/images/beni-ast2500$ ls
# 略
obmc-phosphor-image-beni-ast2500-20230806104538.qemuboot.conf
obmc-phosphor-image-beni-ast2500-20230806104538.rootfs.manifest
obmc-phosphor-image-beni-ast2500-20230806104538.rootfs.squashfs-xz
obmc-phosphor-image-beni-ast2500-20230806104538.static.mtd
obmc-phosphor-image-beni-ast2500-20230806104538.static.mtd.all.tar
obmc-phosphor-image-beni-ast2500-20230806104538.static.mtd.tar
obmc-phosphor-image-beni-ast2500-20230806104538.testdata.json
# 略
到这里就通过我们自己的元数据(配方和配置之类的)构建出了可用的OpenBMC,后续就是往里面增加我们自己的程序,或者修改原有的程序。
增加自定义程序就是增加一个配方,以及相关的代码。在此之前可以先看看在创建Layer的时候增加的那个示例:
jw@HOME:~/openbmc/build$ tree ../meta-beni/ ../meta-beni/ ├── COPYING.MIT ├── README ├── conf │ ├── layer.conf │ ├── machine │ │ └── beni-ast2500.conf │ └── templates │ └── default │ ├── bblayers.conf.sample │ ├── conf-notes.txt │ └── local.conf.sample ├── recipes-example │ └── example │ └── example_0.1.bb # 就是这个 └── recipes-phosphor └── packagegroups └── packagegroup-obmc-apps.bbappend 8 directories, 9 files
它的内容如下:
SUMMARY = "bitbake-layers recipe"
DESCRIPTION = "Recipe created by bitbake-layers"
LICENSE = "MIT"
python do_display_banner() {
bb.plain("***********************************************");
bb.plain("* *");
bb.plain("* Example recipe created by bitbake-layers *");
bb.plain("* *");
bb.plain("***********************************************");
}
addtask display_banner before do_build
实际上它甚至不是一个会编译的OpenBMC的程序,仅仅是一个会在bitbake执行过程中执行的一段代码而已,我们可以通过bitbake命令看到它已经在构建过程中了:
jw@HOME:~/openbmc/build$ bitbake -s | grep example
directfb-examples :1.7.0-r0
example :0.1-r0 # 这个就是我们加进去的
phosphor-ipmi-fru-hostfw-config-example-native :1.0+gitAUTOINC+06514028f8-r1
phosphor-ipmi-fru-inventory-example-native :1.0+gitAUTOINC+06514028f8-r1
phosphor-ipmi-fru-read-inventory-example-native :1.0+gitAUTOINC+68e82947f6-r1
phosphor-led-manager-config-example-native :1.0+gitAUTOINC+b4c82cf41b-r1
phosphor-logging-callouts-example-native :1.0-r1
可以通过bitbake命令直接执行操作:
jw@HOME:~/openbmc/build$ bitbake example Loading cache: 100% |###############################################################################################################| Time: 0:00:00 Loaded 4382 entries from dependency cache. Parsing recipes: 100% |###############################################################################################################| Time: 0:00:00 Parsing of 2708 .bb files complete (2707 cached, 1 parsed). 4383 targets, 566 skipped, 0 masked, 0 errors. NOTE: Resolving any missing task queue dependencies Build Configuration: BB_VERSION = "2.4.0" BUILD_SYS = "x86_64-linux" NATIVELSBSTRING = "ubuntu-20.04" TARGET_SYS = "arm-openbmc-linux-gnueabi" MACHINE = "beni-ast2500" DISTRO = "openbmc-phosphor" DISTRO_VERSION = "nodistro.0" TUNE_FEATURES = "arm thumb arm1176jzs" TARGET_FPU = "soft" meta meta-poky meta-oe meta-networking meta-python meta-phosphor meta-aspeed = "HEAD:67c9d4e715c705cd05fd04f7c8cd4fad300a4666" meta-beni = "master:5a032dd8249100d5e4ac3a1b95c02bcd4eceee44" Initialising tasks: 100% |###############################################################################################################| Time: 0:00:00 Sstate summary: Wanted 7 Local 7 Mirrors 0 Missed 0 Current 123 (100% match, 100% complete) NOTE: Executing Tasks *********************************************** * * * Example recipe created by bitbake-layers * * * *********************************************** NOTE: Tasks Summary: Attempted 531 tasks of which 529 didn't need to be rerun and all succeeded.
从上面可以看到有打印相关信息,它们就来自example.bb中的do_display_banner()
函数。当然这个要第一次执行才会显示,后续在构建的时候就不会执行了,这个时候可以通过如下命令删除之前的构建:
bitbake -c clean example
再次执行bitbake example
就会有显示了。
从以上的结果可以看出,只要将该配方放到recipes-example目录下,就会被执行。这样的话,我们就可以在里面写一个更加像样的配方了:
DESCRIPTION = "Prints Hello World" SRC_URI = "file://helloworld.c" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" do_compile() { ${CC} ${LDFLAGS} ../helloworld.c -o helloworld } do_install() { install -d ${D}${bindir} install -m 0755 helloworld ${D}${bindir} } FILES_${PN} = "${bindir}/helloworld"
关于配方的内容,这里作简单说明:
DESCRIPTION
:对配方的说明。SRC_URI
:配方使用到的源代码。LICENSE
:代码使用的开源许可证。LIC_FILES_CHKSUM
:开源许可证文件的Checksum,这里使用的是通用的MIT许可证,COMMON_LICENSE_DIR
指向的是meta/files/common-licenses
,该目录下包含了所有的开源许可证。do_compile()
:源码编译的方式。do_install()
:生成的二进制的安装方式。FILES_${PN}
:指定需要放到Linux系统中的文件名,PN
在当前示例中的值是helloworld
。bindir
变量的值是/usr/bin
。然后是源代码helloworld.c:
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}
并安装到OpenBMC系统中。最终的目录结果:
├── recipes-example
│ ├── example
│ │ └── example_0.1.bb
│ └── helloworld
│ ├── files
│ │ └── helloworld.c
│ └── helloworld_0.1.bb
此时通过bitbake命令就可以查看到该配方:
jw@HOME:~/openbmc/build$ bitbake -s | grep helloworld
helloworld :0.1-r0
注意能够看到配方并不意味着能够构建到OpenBMC二进制中,同前面之前讲到的webui-vue一样,我们也需要将配方到特定的配置中,这里还是放到meta-beni/recipes-phosphor/packagegroups/packagegroup-obmc-apps.bbappend:
RDEPENDS:${PN}-extras:append = "webui-vue helloworld"
之后再重新构建OpenBMC,并使用QEMU启动新的二进制,可以在OpenBMC的Shell中操作新增的helloworld程序:
root@beni-ast2500:~# ls /usr/bin/helloworld
/usr/bin/helloworld
root@beni-ast2500:~# helloworld
Hello World!
到这里我们就已经新增了一个自己的程序了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。