【BMC】OpenBMC开发基础1:自定义项目和程序

前言

在进行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(获取项目)的时候,实际上就是创建了一个自己用的分层,这里我们会放置我们自己的程序。

  1. 首先还是要准备构建环境。之前使用的是OpenBMC带的setup,但是为了创建自己的环境,可以使用OE自带的环境配置脚本:
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 the PATH 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##变成了实际的绝对路径。还要注意这里也有BBPATHBBFILES,它会替换前面提到的beni-ast2500.conf中的值。

conf-notes.txt中的内容会在执行setup之后打印出来,告知可通过bitbake构建的二进制。

local.conf.sample里面也定义了一系列的变量,并会直接变成build/conf目录下的local.conf,内容不会发生变化。

上述的conf文件,最终就是定义了路径和一大堆的变量。路径比较好理解,就是用来定位文件;变量到后续使用到的时候再分析。

  1. 之后删掉build下面的cache和conf目录(因为前面编译过ast2500-evb,需要进行清理),然后重新执行setup:
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目录下,作为全局的配置。

  1. 再之后就是bitbake的重新构建,最终得到:
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在当前示例中的值是helloworldbindir变量的值是/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!

到这里我们就已经新增了一个自己的程序了。

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值