嵌入式Linux下使用 Plymouth 实现开机画面示例
1). 简介
嵌入式 Linux 下传统实现 Splash Screen 的方式是通过替换 kernel 默认的 TUX 小企鹅 logo 为定制的开机画面图片来实现嵌入式设备开机图片,虽然比较成熟且可以保证开机画面加载比较早,但是存在的问题首先是对嵌入式设备不同显示接口的兼容性不好,另外每次修改适配都需要重新编译内核,维护起来不是很方便,然后就是只能支持静态图片无法支持动画。基于上述原因,使用专门的 Splash Screen 工具来实现开机画面逐渐成为嵌入式设备的主流方向,本文就简单演示使用 Plymouth 工具来实现动态开机画面的示例。
本文所演示的平台来自于Toradex Verdin iMX8MM 嵌入式平台,基于 NXP iMX8M Mini 系列 ARM 处理器,主要核心架构为 Cortex-A53 。
2). 硬件准备
a).
核心版配合 载板,并通过 DSI-LVDS Adapter 连接 以及调试串口以便测试。3). 关于 Plymouth
a). Plymouth 是一个实现 Linux 启动过程中开机画面的工具软件,其启动的时间非常早,通过 initramfs 帮助可以在 Linux 内核加载同时启动,甚至要早于 Linux rootfs 文件系统挂载。Plymouth 可以方便的实现开关机图片或者动画。
b). 关于 Plymouth 更多详细介绍以及源代码请自行参考如下资料。
./ Plymouth 官方页面
./ Plymouth 源代码
./ Plymouth 深入配置使用说明
4). 通过 Ycoto 环境配置 Plymouth 并编译 Ycoto Linux BSP Image
a). 配置 Ycoto Project 编译环境
./ 参考这里配置基本的 Ycoto Project 编译环境
./ 参考如下文章配置定制化 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 相关配置文件
./ 增加 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 图标会被遮盖,实际使用可以根据需要修改图片文件和 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 是文件系统组件,通过 Linux kernel 加载完成后在使能systemd 来启动,这样就会导致比较大的延迟;为了尽可能使 Plymouth 在系统启动过程中尽早启动,可以添加包含 Plymouth 的 Initramfs 镜像使得 Plymouth 在 Linux Kernel 加载过程中即同步启动了。
./ 添加 Initramfs bb 定义以及相关文件,对应需要 files 目录下的相关文件请参考
---------------------------------------
$ 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 来调整启动进程,这里通过修改 u-boot-distro-boot 文件来适配,对应的 files 目录下的文件完整内容请参考
---------------------------------------
$ 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 来实现的,为了使得在 initramfs 阶段就可以加载相关驱动,需要修改 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 文件请见
,主要修改了如下几个驱动的配置---------------------------------------
-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 文件结构如下
---------------------------------------
$ 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 压缩包内,需要修改如下 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 文件添加相关 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 相关定义
---------------------------------------
# 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 环境变量来显示 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). 最后部署完成的测试效果如下,实测从开机到出现 Splash 画面大约5秒,另外 Plymouth splash 默认除了支持开机画面,在 reboot 重启和 poweroff 关机的时候也会同样显示 splash 画面
动画演示如下
6). 总结
本文基于嵌入式 Linux 简单演示了 Plymouth splash 开机画面的部署和测试。
提交
Verdin AM62 LVGL 移植
基于 NXP iMX8MM 测试 Secure Boot 功能
隆重推出 Aquila - 新一代 Toradex 计算机模块
Verdin iMX8MP 调试串口更改
NXP iMX8MM Cortex-M4 核心 GPT Capture 测试