嵌入式Linux下使用 Plymouth 實(shí)現(xiàn)開機(jī)畫面示例
1). 簡介
嵌入式 Linux 下傳統(tǒng)實(shí)現(xiàn) Splash Screen 的方式是通過替換 kernel 默認(rèn)的 TUX 小企鵝 logo 為定制的開機(jī)畫面圖片來實(shí)現(xiàn)嵌入式設(shè)備開機(jī)圖片,雖然比較成熟且可以保證開機(jī)畫面加載比較早,但是存在的問題首先是對嵌入式設(shè)備不同顯示接口的兼容性不好,另外每次修改適配都需要重新編譯內(nèi)核,維護(hù)起來不是很方便,然后就是只能支持靜態(tài)圖片無法支持動畫?;谏鲜鲈?,使用專門的 Splash Screen 工具來實(shí)現(xiàn)開機(jī)畫面逐漸成為嵌入式設(shè)備的主流方向,本文就簡單演示使用 Plymouth 工具來實(shí)現(xiàn)動態(tài)開機(jī)畫面的示例。
本文所演示的平臺來自于Toradex Verdin iMX8MM 嵌入式平臺,基于 NXP iMX8M Mini 系列 ARM 處理器,主要核心架構(gòu)為 Cortex-A53 。
2). 硬件準(zhǔn)備
a).
核心版配合 載板,并通過 DSI-LVDS Adapter 連接 以及調(diào)試串口以便測試。3). 關(guān)于 Plymouth
a). Plymouth 是一個實(shí)現(xiàn) Linux 啟動過程中開機(jī)畫面的工具軟件,其啟動的時間非常早,通過 initramfs 幫助可以在 Linux 內(nèi)核加載同時啟動,甚至要早于 Linux rootfs 文件系統(tǒng)掛載。Plymouth 可以方便的實(shí)現(xiàn)開關(guān)機(jī)圖片或者動畫。
b). 關(guān)于 Plymouth 更多詳細(xì)介紹以及源代碼請自行參考如下資料。
./ Plymouth 官方頁面
./ Plymouth 源代碼
./ Plymouth 深入配置使用說明
4). 通過 Ycoto 環(huán)境配置 Plymouth 并編譯 Ycoto Linux BSP Image
a). 配置 Ycoto Project 編譯環(huán)境
./ 參考這里配置基本的 Ycoto Project 編譯環(huán)境
./ 參考如下文章配置定制化 layer
b). 在定制化 layer meta-customer-demos 下面添加 layer 配置文件
---------------------------------------
$ mkdir -p ../oe_core/layers/meta-customer-demos/conf
$ cd .../oe_core/layers/meta-customer-demos/conf
### create layer.conf file ###
# We have a conf and classes directory, append to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "customer-demos"
BBFILE_PATTERN_customer-demos = "^${LAYERDIR}/"
BBFILE_PRIORITY_customer-demos = "24"
# Let us add layer-specific bbappends which are only applied when that
# layer is included in our configuration
BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bbappend' % layer \
for layer in BBFILE_COLLECTIONS.split())}"
# Add layer-specific bb files too
BBFILES += "${@' '.join('${LAYERDIR}/%s/recipes*/*/*.bb' % layer \
for layer in BBFILE_COLLECTIONS.split())}"
LAYERDEPENDS_customer-demos = " \
core \
yocto \
openembedded-layer gnome-layer multimedia-layer networking-layer \
"
LAYERSERIES_COMPAT_customer-demos = "hardknott honister kirkstone"
---------------------------------------
c). 在定制化 layer meta-customer-demos 下面添加 Plymouth 相關(guān)配置文件
./ 增加 Plymouth bb file
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-core/plymouth
$ cd recipes-core/plymouth
### cteate plymouth_%.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI += " \ file://toradexlogo-white.png \ file://spinner.plymouth \ " PACKAGECONFIG = "pango drm" EXTRA_OECONF += "--with-udev --with-runtimedir=/run" do_install:append () { install -m 0644 ${WORKDIR}/toradexlogo-white.png ${D}${datadir}/plymouth/themes/spinner/watermark.png install -m 0644 ${WORKDIR}/spinner.plymouth ${D}${datadir}/plymouth/themes/spinner/spinner.plymouth }
---------------------------------------
./ 添加 Plymouth 使用的 theme 文件 和 background logo 圖片文件,這里使用的是一個配合屏幕分辨率的白色背景圖片,因此 spinner 圖標(biāo)會被遮蓋,實(shí)際使用可以根據(jù)需要修改圖片文件和 theme 配置。
---------------------------------------
$ mkdir files
$ cp .../toradexlogo-white.png files
$ cd files
### cteate spinner theme file spinner.plymouth ###
[Plymouth Theme]
Name=Spinner
Description=Adoption of official Spinner Theme for Toradex.
ModuleName=two-step
[two-step]
Font=Cantarell 12
TitleFont=Cantarell Light 30
ImageDir=/usr/share/plymouth/themes/spinner
DialogHorizontalAlignment=.5
DialogVerticalAlignment=.382
TitleHorizontalAlignment=.5
TitleVerticalAlignment=.382
HorizontalAlignment=.5
VerticalAlignment=.7
WatermarkHorizontalAlignment=.5
WatermarkVerticalAlignment=.45
Transition=none
TransitionDuration=0.0
BackgroundStartColor=0x000000
BackgroundEndColor=0x000000
ProgressBarBackgroundColor=0x606060
ProgressBarForegroundColor=0xffffff
MessageBelowAnimation=true
---------------------------------------
d). 由于 Plymouth 是文件系統(tǒng)組件,通過 Linux kernel 加載完成后在使能systemd 來啟動,這樣就會導(dǎo)致比較大的延遲;為了盡可能使 Plymouth 在系統(tǒng)啟動過程中盡早啟動,可以添加包含 Plymouth 的 Initramfs 鏡像使得 Plymouth 在 Linux Kernel 加載過程中即同步啟動了。
./ 添加 Initramfs bb 定義以及相關(guān)文件,對應(yīng)需要 files 目錄下的相關(guān)文件請參考
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/recipes-core
$ mkdir -p initramfs-framework/files
$ cd initramfs-framework
### cteate initramfs-framework_1.0.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI += "\
file://plymouth \
file://kmod \
file://0001-Mount-run-with-tmpfs.patch \
file://0002-only-scan-for-block-devices.patch \
"
PACKAGES:append = " \
initramfs-module-plymouth \
initramfs-module-kmod \
"
SUMMARY:initramfs-module-plymouth = "initramfs support for plymouth"
RDEPENDS:initramfs-module-plymouth = "${PN}-base plymouth ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd-udev-rules', '', d)}"
FILES:initramfs-module-plymouth = "/init.d/02-plymouth"
SUMMARY:initramfs-module-kmod = "initramfs support for loading kernel modules"
RDEPENDS:initramfs-module-kmod = "${PN}-base"
FILES:initramfs-module-kmod = "\
/init.d/01-kmod \
/etc/modules-load.d/* \
"
do_install:append() {
install -m 0755 ${WORKDIR}/plymouth ${D}/init.d/02-plymouth
install -m 0755 ${WORKDIR}/kmod ${D}/init.d/01-kmod
}
# Adding modules so plymouth can show the splash screen during boot
SRC_URI:append:mx8-nxp-bsp = " file://50-imx8-graphics.conf"
RDEPENDS:initramfs-module-kmod:append:mx8-nxp-bsp = " \
kernel-module-display-connector \
kernel-module-lontium-lt8912b \
"
do_install:append:mx8-nxp-bsp() {
install -d ${D}/etc/modules-load.d/
install -m 0755 ${WORKDIR}/50-imx8-graphics.conf ${D}/etc/modules-load.d/50-imx8-graphics.conf
}
---------------------------------------
./ 添加 initramfs image 定義文件
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/recipes-core
$ mkdir images
$ cd images
### cteate initramfs-plymouth-splash-image.bb file ###
DESCRIPTION = "Toradex plymouth splash demo initramfs image"
PACKAGE_INSTALL = "initramfs-framework-base initramfs-module-udev \
initramfs-module-rootfs initramfs-module-debug \
initramfs-module-plymouth ${VIRTUAL-RUNTIME_base-utils} base-passwd \
initramfs-module-kmod"
SYSTEMD_DEFAULT_TARGET = "initrd.target"
# Do not pollute the initrd image with rootfs features
IMAGE_FEATURES = "splash"
export IMAGE_BASENAME = "initramfs-plymouth-splash-image"
IMAGE_LINGUAS = ""
LICENSE = "MIT"
IMAGE_FSTYPES = "cpio.gz"
IMAGE_FSTYPES:remove = "wic wic.gz wic.bmap wic.vmdk wic.vdi ext4 ext4.gz teziimg"
IMAGE_CLASSES:remove = "image_type_torizon image_types_ostree image_types_ota image_repo_manifest license_image qemuboot"
# avoid circular dependencies
EXTRA_IMAGEDEPENDS = ""
inherit core-image nopackages
IMAGE_ROOTFS_SIZE = "8192"
# Users will often ask for extra space in their rootfs by setting this
# globally. Since this is a initramfs, we don't want to make it bigger
IMAGE_ROOTFS_EXTRA_SPACE = "0"
IMAGE_OVERHEAD_FACTOR = "1.0"
BAD_RECOMMENDATIONS += "busybox-syslog"
---------------------------------------
e). 由于增加了 initramfs image,就需要修改 distroboot 啟動文件 boot.scr 來調(diào)整啟動進(jìn)程,這里通過修改 u-boot-distro-boot 文件來適配,對應(yīng)的 files 目錄下的文件完整內(nèi)容請參考
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-bsp/u-boot/files
$ cd recipes-bsp/u-boot
### cteate u-boot-distro-boot.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
SRC_URI:append = " \
file://boot.cmd.in \
"
---------------------------------------
f). 另外,對于 Verdin iMX8M Mini,由于顯示部分是通過 DSI-LVDS Bridge 來實(shí)現(xiàn)的,為了使得在 initramfs 階段就可以加載相關(guān)驅(qū)動,需要修改 Linux Kernel 配置,而對于其他 iMX8/iMX8X/iMX8MP 如果是原生 LVDS/HDMI 接口則無需修改。
---------------------------------------
$ cd .../oe_core/layers/meta-customer-demos/
$ mkdir -p recipes-kernel/linux/files
$ cd recipes-kernel/linux
### cteate linux-toradex%.bbappend file ###
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
# Prevent the use of in-tree defconfig
unset KBUILD_DEFCONFIG
SRC_URI += "\
file://defconfig \
"
---------------------------------------
./ files 目錄下的完整 defconfig 文件請見
,主要修改了如下幾個驅(qū)動的配置---------------------------------------
-CONFIG_DRM_PANEL_LVDS=m
+CONFIG_DRM_PANEL_LVDS=y
-CONFIG_DRM_SEC_MIPI_DSIM=m
+CONFIG_DRM_SEC_MIPI_DSIM=y
-CONFIG_DRM_TI_SN65DSI83=m
+CONFIG_DRM_TI_SN65DSI83=y
-CONFIG_DRM_IMX_SEC_DSIM=m
+CONFIG_DRM_IMX_SEC_DSIM=y
---------------------------------------
g). 最后配置完成的 meta-customer-demos 文件結(jié)構(gòu)如下
---------------------------------------
$ tree meta-customer-demos/
meta-customer-demos/
├── conf
│ └── layer.conf
├── recipes-bsp
│ └── u-boot
│ ├── files
│ │ └── boot.cmd.in
│ └── u-boot-distro-boot.bbappend
├── recipes-core
│ ├── images
│ │ ├── initramfs-ostree-torizon-image.bb
│ │ └── initramfs-plymouth-splash-image.bb
│ ├── initramfs-framework
│ │ ├── files
│ │ │ ├── 0001-Mount-run-with-tmpfs.patch
│ │ │ ├── 0002-only-scan-for-block-devices.patch
│ │ │ ├── 50-imx8-graphics.conf
│ │ │ ├── kmod
│ │ │ ├── plymouth
│ │ │ └── rootfs
│ │ └── initramfs-framework_1.0.bbappend
│ └── plymouth
│ ├── files
│ │ ├── spinner.plymouth
│ │ └── toradexlogo-white.png
│ └── plymouth_%.bbappend
└── recipes-kernel
└── linux
├── files
│ └── defconfig
└── linux-toradex%.bbappend
13 directories, 17 files
---------------------------------------
h). 為了將 initramfs 集成到編譯生成的 Image 壓縮包內(nèi),需要修改如下 image_type 配置文件
---------------------------------------
--- a/layers/meta-toradex-bsp-common/classes/image_type_tezi.bbclass
+++ b/layers/meta-toradex-bsp-common/classes/image_type_tezi.bbclass
@@ -8,7 +8,7 @@
WKS_FILE_DEPENDS:append = " tezi-metadata virtual/dtb"
DEPENDS += "${WKS_FILE_DEPENDS}"
IMAGE_BOOT_FILES_REMOVE = "${@make_dtb_boot_files(d) if d.getVar('KERNEL_IMAGETYPE') == 'fitImage' else ''}"
-IMAGE_BOOT_FILES:append = " overlays.txt ${@'' if d.getVar('KERNEL_IMAGETYPE') == 'fitImage' else 'overlays/*;overlays/'}"
+IMAGE_BOOT_FILES:append = " overlays.txt initramfs-plymouth-splash-image-${MACHINE}.cpio.gz;initramfs-plymouth-splash-image.img ${@'' if d.getVar('KERNEL_IMAGETYPE') == 'fitImage' else 'overlays/*;overlays/'}"
IMAGE_BOOT_FILES:remove = "${IMAGE_BOOT_FILES_REMOVE}"
RM_WORK_EXCLUDE += "${PN}"
---------------------------------------
i). 修改 build/conf/bblayer.conf 文件添加相關(guān) layer
---------------------------------------
--- a/build/conf/bblayers.conf 2023-03-30 11:13:22.946533642 +0800
+++ b/build/conf/bblayers.conf 2023-11-17 16:03:01.666129480 +0800
@@ -35,6 +35,7 @@
${TOPDIR}/../layers/meta-freescale-distro \
${TOPDIR}/../layers/meta-toradex-demos \
${TOPDIR}/../layers/meta-qt5 \
+ ${TOPDIR}/../layers/meta-customer-demos \
\
\
${TOPDIR}/../layers/meta-toradex-distro \
---------------------------------------
j). 修改 build/conf/local.conf 文件,增加 Plymouth 和 initramfs 相關(guān)定義
---------------------------------------
# add plymouth support
CORE_IMAGE_EXTRA_INSTALL += "plymouth"
INITRAMFS_IMAGE = "initramfs-plymouth-splash-image"
INITRAMFS_FSTYPES = "cpio.gz"
---------------------------------------
k). 重新編譯生成 Ycoto Linux BSP Image
---------------------------------------
$ MACHINE="verdin-imx8mm" PARALLEL_MAKE="-j 4" BB_NUMBER_THREADS="4" bitbake tdx-reference-multimedia-image
---------------------------------------
l). 參考
的說明將上述修改下重新編譯生成的 Ycoto Linux Image 通過 Toradex Easy Installer 更新到 Verdin iMX8MM 模塊。
5). Plymouth Splash 部署測試
a). 安裝好上述編譯的 Image 后,參考
說明配置合適的 Device-tree Overlay 文件來適配屏幕;然后配置如下 U-boot 環(huán)境變量來顯示 Splash,且縮短加載時間---------------------------------------
# setenv tdxargs ‘quiet logo.nologo vt.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3’
# setenv bootdelay 0
# saveenv && reset
---------------------------------------
b). 為了保證 Plymouth Splash和 Qt Demo App切換更自然,且中間不會被 Weston Desktop 中斷,需要修改一下一些 Systemd Service 文件
---------------------------------------
--- a/lib/systemd/system/plymouth-quit.service
+++ b/lib/systemd/system/plymouth-quit.service
@@ -1,6 +1,6 @@
[Unit]
Description=Terminate Plymouth Boot Screen
-After=rc-local.service plymouth-start.service systemd-user-sessions.service
+After=rc-local.service plymouth-start.service systemd-user-sessions.service waylan
d-app-launch.service
[Service]
ExecStart=-/bin/plymouth quit --retain-splash
--- a/lib/systemd/system/serial-getty@.service
+++ b/lib/systemd/system/serial-getty@.service
@@ -12,7 +12,7 @@
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
BindsTo=dev-%i.device
-After=dev-%i.device systemd-user-sessions.service plymouth-quit-wait.service getty
-pre.target
+After=dev-%i.device systemd-user-sessions.service getty-pre.target
After=rc-local.service
# If additional gettys are spawned during boot then we should make
--- a/lib/systemd/system/weston.service
+++ b/lib/systemd/system/weston.service
@@ -13,7 +13,7 @@
After=systemd-user-sessions.service
# If Plymouth is used, we want to start when it is on its way out.
-After=plymouth-quit-wait.service
+#After=plymouth-quit-wait.service
# D-Bus is necessary for contacting logind. Logind is required.
Wants=dbus.socket
--- a/etc/xdg/weston/weston.ini
+++ b/etc/xdg/weston/weston.ini
@@ -6,6 +6,7 @@
repaint-window=16
#enable-overlay-view=1
modules=screen-share.so
+shell=kiosk-shell.so
#[shell]
#size=1920x1080
---------------------------------------
b). 最后部署完成的測試效果如下,實(shí)測從開機(jī)到出現(xiàn) Splash 畫面大約5秒,另外 Plymouth splash 默認(rèn)除了支持開機(jī)畫面,在 reboot 重啟和 poweroff 關(guān)機(jī)的時候也會同樣顯示 splash 畫面
動畫演示如下
6). 總結(jié)
本文基于嵌入式 Linux 簡單演示了 Plymouth splash 開機(jī)畫面的部署和測試。
提交
Verdin AM62 LVGL 移植
基于 NXP iMX8MM 測試 Secure Boot 功能
隆重推出 Aquila - 新一代 Toradex 計算機(jī)模塊
Verdin iMX8MP 調(diào)試串口更改
NXP iMX8MM Cortex-M4 核心 GPT Capture 測試