最近被問到一題,你知道要怎麼在OpenBMC建立一個自己的專案嗎?這個故事...說起來可能很長,我腦中還沒有一個藍圖可以瞬間把他講解清楚。但有一些必要的設定,是我目前能想到的比較重要的部分,那我就來把它稍微整理總結一下。看看對大家有沒有幫助?如果你也正在嘗試建立自己的專案,但是有點卡住了,也許可以檢查一下這些設定是否都有被設置正確。
當你要在 OpenBMC 中建立一個新的專案(例如支援新的主機板或平台)時,理解整個專案的目錄結構是非常關鍵的第一步。OpenBMC 是一個基於 Yocto Project 的嵌入式 Linux 發行版,因此它的架構是由多層 meta layer 組成。每個 layer 都負責不同的功能或硬體平台。先把Github打開到OpenBMC這一頁面:https://github.com/openbmc/openbmcopenbmc/:整個專案的根目錄,包含所有層(meta layers)、設定檔與工具。meta-phosphor/:核心層,定義了 OpenBMC 通用功能(如 D-Bus 服務、systemd、日誌、使用者管理等)。meta-openembedded/:上游共用軟體層,提供 Yocto 環境中常見的第三方套件。meta-<vendor>/:各廠商或平台的專屬層(例如meta-facebook、meta-ibm、meta-aspeed)。每個 layer 通常會再細分為多個機種。meta-yourboard/(你要新增的專案):此層是你為新硬體或客製功能所建立的 layer。(例如:meta-facebook/meta-ventura/、meta-ibm/meta-rainier/這類目錄。)
最早期我真的完全不懂Yocto這玩意,也沒有自己創立一個專案的概念的時候,最土法煉鋼的一個方式就是把別人的整個專案複製一份, 然後去搜尋複製過來的專案名稱,一一的去研究大家針對這個專案有哪些必要的設定和改動。(這個方法很爛,但是我還是想講,因為這可能是沒招的時候保命的一招,去看看別人的修改,在詳細去了解他為什麼要做這個修改,這個過程讓我慢慢認識Yocto以及很多的設定,畢竟工作中很難有時間可以跟老闆說,請給我一個月的時間先來學習所有一切背景知識,然後我們再開始....
XD (讓我使用一下這個保育類表情符號)。
到這一步,你應該已經瞭解到目錄有很多層這件事情,所以後面我們會反覆地提到Layer,大家就不會太不適應了,此時我們創建出了citybonnie這家公司的目錄meta-citybonnie以及屬於Taiwan number one的目錄,叫做meta-taiwanno1。所以citybonnie這家公司要開始製作一個台灣第一的專案。
建立新的Layer對Yocto的意義?
在 Yocto 專案裡,「Layer」是邏輯分層(Logical Layer)。每一層代表一組組態或特定領域的 recipes,彼此獨立又可以疊加。 舉例來說:
meta是 Yocto 官方核心層;meta-phosphor是 OpenBMC 的共通層;meta-citybonnie/meta-taiwanno1則是針對某台伺服器機種的專用層。
建立新 layer 的目的,是讓不同平台能在共用架構之下仍能客製化,例如:
- 使用不同的 kernel 或 U-Boot 組態;
- 自訂感測器或風扇策略;
- 定義自家映像(Image)組成。
所以,當我們要開發「TaiwanNo.1」這台主機的 BMC 時,就需要一個新的 layer 來放置它的設定與擴充。
建立Layer的起點:conf/layer.conf
layer.conf 是整個 layer 的「身份宣告」與「行為定義」。沒有它,BitBake 完全不知道這個資料夾存在。 它的主要任務有三個:
- 告訴 BitBake:這個 layer 在哪裡(
BBPATH、BBFILES)。 - 告訴 Yocto:這個 layer 的名稱、優先權、相依關係。
- 告訴建構系統:它支援哪些 Yocto 版本(
LAYERSERIES_COMPAT)。
以下是一份簡化的meta-taiwanno1範例:
# 我們有 conf 和 classes 目錄,加入 BBPATH 搜尋
BBPATH .= ":${LAYERDIR}"
# 我們有 recipes-* 目錄,加入 BBFILES 掃描範圍
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
# 註冊這個 Layer 的名稱與範圍
BBFILE_COLLECTIONS += "taiwanno1-layer"
BBFILE_PATTERN_taiwanno1-layer := "^${LAYERDIR}/"
# 定義這個 Layer 相容的 Yocto 發行版本
LAYERSERIES_COMPAT_taiwanno1-layer := "kirkstone scarthgap"
# 指定優先權(數字越大,覆寫優先)
BBFILE_PRIORITY_taiwanno1-layer = "7"
想像 Yocto 在啟動時讀取所有 layer,它會先看 bblayers.conf 裡列了哪些層,然後逐一打開它們的 layer.conf。PS.最後這個指定優先權讓 BitBake 在處理 %.bbappend 時知道優先順序。這樣可確保你的 bbappend 能覆蓋 meta-phosphor 或 meta-openbmc 的定義。這很重要,不然有時候你寫的東西被覆蓋了,你會不知道為什麼???為什麼沒build到我的???
定義機器(machine definition)
這段開始你可以自行打開參考任何一個專案的conf/machine/xxx.conf檔案作爲參考來閱讀以下我寫的內容。如果你要建立自己的專案(例如 meta-taiwanno1),那麼對應的檔案就會是:
meta-taiwanno1/conf/machine/taiwanno1.conf
這個 .conf 檔是 Yocto build 系統辨認「這是什麼樣的硬體平台」的關鍵,裡面會定義出:要用哪一個 SoC、要用什麼 kernel device tree、要怎麼組合 rootfs、要載入哪些包含檔案(include),以及一些建構用變數。
每個機器檔開頭通常會有簡單的註解,說明用途。這部分看似簡單,但在多平台專案裡非常實用。當你的同事開另一個專案時,他們會快速從這個註解知道這個檔案屬於哪個專案分支、誰維護、主要用途為何。建議在實際開發中,也可以補上硬體版本(例如「BMC for Taiwanno1 Gen2」)或 SOC 型號。接下來最重要的設定,是指定核心與開機載入的裝置樹:
KMACHINE = "aspeed"
KERNEL_DEVICETREE = "aspeed/aspeed-ast2600-evb.dtb"
KMACHINE 表示底層使用的 SOC 平台,這裡的 "aspeed" 對應到 Aspeed 系列晶片(AST2600 是目前 BMC 的主流選擇)。KERNEL_DEVICETREE 則決定 kernel 在編譯時要帶入的 device tree(.dtb)檔案。如果你的硬體尚未在 kernel 目錄中新增 taiwanno1 的 .dts,你可以先暫時使用一個相近的範例,如 aspeed-ast2600-evb.dtb。等你未來在 Linux kernel 加入 taiwanno1 的裝置樹,這行可以改成:
KERNEL_DEVICETREE = "aspeed/aspeed-ast2600-taiwanno1.dtb"
這樣 Yocto build 時就會自動選用你自己的硬體描述檔。
Note: DTS這可能又是另外一個主題,如果還不是非常了解,我下次可以來寫寫這塊。
除了定義Kernel之外,我們也需要定義U-boot。UBOOT_MACHINE 指定要使用的 defconfig 名稱,這是 U-Boot 編譯的核心設定檔。如果你的硬體設計與 AST2600 EVB 相似,可以沿用 ast2600_openbmc_spl_defconfig。未來若要客製,可複製一份新的 defconfig 檔放入 u-boot 層裡。UBOOT_DEVICETREE 指定開機階段使用的裝置樹版本。有些專案會命名為 ast2600-taiwanno1,這樣可對應專用的電源序列與 GPIO 定義。其他像是SPL_BINARY 是第二階段開機程式(SPL)的檔案路徑、SOCSEC_SIGN_ENABLE 用來啟用安全開機簽章(Secure Boot)。若你還沒導入簽章流程,可以暫時設為 0。這些比較Project specific或是跟你使用的chip相關的自定義,大家就等有實體的專案和硬體的時候再去仔細研究他可以做的設定即可。
接下來這一串 require 是 machine 檔最核心的部分:
require conf/distro/include/phosphor-static-norootfs.inc
require conf/distro/include/pldm.inc
require conf/machine/include/facebook-compute-singlehost.inc
require conf/machine/include/ast2600.inc
require conf/machine/include/obmc-bsp-common.inc
require conf/machine/include/facebook-tpm2.inc
require conf/machine/include/facebook-ncsi-nic.inc
每一個 require 都是把一段通用設定 include 進來。這讓你的 machine 不需要重複寫一堆重複變數。
ast2600.inc提供了 Aspeed 晶片的基本設定(像 CPU 架構、交叉編譯參數)。obmc-bsp-common.inc是 OpenBMC 官方提供的 BSP 基礎設定。pldm.inc、tpm2.inc、ncsi-nic.inc這些是功能性模組(PLDM、TPM、網卡通訊)。如果你的板子暫時沒有支援,可以先拿掉。
這樣做的好處是:未來要維護時,不必去改 machine 檔,只要調整共用的 .inc 即可。
在定義機器的最後是定義 Flash 大小。
FLASH_SIZE = "131072"
VIRTUAL-RUNTIME_obmc-host-state-manager = "phosphor-state-manager-host"
VIRTUAL-RUNTIME_obmc-chassis-state-manager = "phosphor-state-manager-chassis"
FLASH_SIZE決定了整個 BMC 映像檔的可用容量(這裡是 128MB)。- 兩個
VIRTUAL-RUNTIME_的設定是 Yocto 的虛擬依賴機制:
它讓 BitBake 知道這台機器要使用哪個軟體來實現「主機狀態管理」與「機箱狀態管理」。 這些名稱對應到phosphor-state-manager專案的不同變體。例如,phosphor-state-manager-host負責偵測主機上電、關機等狀態。
建構環境樣板:bblayers.conf.sample 與 local.conf.sample
很多人初看這兩個檔案會以為它們沒用,其實它們是整個 layer 的「範例模板」。
在 meta-facebook/meta-yosemite4/conf/templates/default/ 中,你可以看到:
bblayers.conf.samplelocal.conf.sampleconf-notes.txt
它們並不會直接參與編譯,但當你執行 source setup <machine> 或 oe-init-build-env 時,這些樣板會被複製到 build/conf/ 目錄下,變成真正的:
build/conf/bblayers.conf
build/conf/local.conf
這邊講一下bblayers.conf.sample 的意義,它定義整個專案的 layer 結構。例如在 taiwanno1 裡可能是:
BBLAYERS ?= " \
${TOPDIR}/../poky/meta \
${TOPDIR}/../openbmc/meta-openembedded/meta-oe \
${TOPDIR}/../openbmc/meta-phosphor \
${TOPDIR}/../openbmc/meta-taiwanno1 \
"
這份清單決定了 Yocto 會去掃描哪些層。少了它,BitBake 甚至不會讀取你的 layer.conf。
而local.conf.sample是開發者個人設定範本,例如:
- 預設機器名稱;
- 影像類型;
- 效能優化;
- 環境變數。
這讓不同開發者在相同基底下,可以快速複製環境。
整合 Bootloader 與 Kernel:bbappend 與 cfg
在 Yosemite系列的初始 commit 裡,可以看到兩個關鍵結構:
recipes-bsp/u-boot/u-boot-aspeed-sdk_%.bbappend
recipes-bsp/u-boot/u-boot-aspeed-sdk/yosemiteX.cfg
recipes-kernel/linux/linux-aspeed_%.bbappend
recipes-kernel/linux/linux-aspeed/yosemiteX.cfg
這四個檔案構成「平台 Bring-up 的第一步」。
u-boot bbappend
這種命名(_%.bbappend)代表它會附加到所有版本的 u-boot-aspeed-sdk.bb。裡面通常只指定要使用的配置檔:
SRC_URI:append = " file://yosemiteX.cfg"
這樣就能覆蓋 U-Boot 預設設定。
u-boot cfg
這是一個小而重要的檔案,像這樣:這些設定決定了開機階段的序列埠、核心參數等。
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyS4,57600n8 root=/dev/ram rw vmalloc=768M"
CONFIG_BAUDRATE=57600
kernel bbappend 與 cfg
同理,kernel 部分:
SRC_URI:append = " file://yosemiteX.cfg"
在 .cfg 中可能會設定 device tree、驅動開啟、或記憶體對應。這樣的設計允許每個平台在共用同一套 kernel 原始碼時,仍可自訂細節。
Firmware Image的配方
在 Yocto 的世界裡,「image」 這個詞指的是「最終要被編譯出來的映像檔」——也就是我們最後會燒進板子的 .wic、.bin 或 .squashfs。而每個映像檔的「內容組成」則是由一個或多個 .bb 或 .inc 檔來描述,這些檔會列出要安裝的套件、工具與服務。
OpenBMC 的核心專案 meta-phosphor 裡面已經定義了「通用型」的影像配方,例如:
phosphor-image.bbphosphor-image.incobmc-phosphor-image.bb
它們定義了最基本的 BMC 功能(例如 D-Bus、systemd、REST API、redfish、sensors、networkd 等)。但是每個硬體平台都可能需要一些「額外功能」。例如:特定的 GPIO 偵測行為/主機電源控制(power control)/硬體監控 sensor 的額外邏輯/ debug card、按鈕、LED 或 MCTP 設定。所以各個專案都會建立自己專屬的 image 設定檔,去在通用 image 基礎上附加平台特有的套件。具體可能會寫些什麼?大家可以參考一下最新的專案底下有這個檔案的內容。
meta-facebook/meta-[project]/recipes-phosphor/images/xxx-phosphor-image.inc
天啊!寫到這邊我看了一下右下角,方格子提醒我以上的內容需要花上將近20分鐘閱讀,我可以感覺到被棄讀的可能性大大的提高...就先寫到這裡了。還有什麼其他想知道,或是不清楚的,可以在下方留言區留言告訴我喔!













