NXP LSDK系统不挂载`/boot`分区,背后的原因让人暖心...

故障现象

有些使用LSDK编译生成的系统镜像在安装至SD卡或eMMC并放入目标板卡启动后,不会自动挂载/boot分区;然而根据LSDK的设计,/lib/modules实际上是指向/boot/modules的软链接,因此boot分区挂载失败会内核驱动加载失败。

故障分析

1. 目标系统分析

在目标板卡上观察到,systemd报错的首个服务为/etc/systemd/system/boot.mount,通过journalctl可看到其日志中包含一条:

1
mount: /boot: can't find UUID=PARTUUID.

这条消息提示自动挂载的参数配置有问题。/etc/systemd/system/boot.mount服务文件的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Boot Partition
Before=systemd-modules-load.service

[Mount]
What=UUID=PARTUUID
Where=/boot
Type=ext4
Options=defaults

[Install]
WantedBy=local-fs.target

可见,其UUID并未被正确修改,导致挂载失败。

通过grep等工具对自启动的脚本及服务简要排查后,可以确定该参数不是在目标板卡上进行配置的。

2. 宿主系统分析

由于故障涉及目标系统的运行,而导致故障的参数具有动态的特性,初步推断问题出在烧录工具flex-installer上面。通过vim `which flex-installer`,并在文件中搜索UUID=字符串,可在350行左右发现boot分区UUID的更新机制:

1
uuid_boot=$(lsblk -l --output UUID $bootdev | grep -)

理想状态下这行代码在一部分操作系统中可以返回正确的UUID(如我的主机,使用openSUSE):

1
2
3
4
5
6
7
8
$ lsblk -o uuid
UUID

556da6b9-ddc2-4756-8c9e-b311202de87c

f038c45b-2cdb-40d6-9d6c-9dd20825885a
0cffebb3-3287-4fb4-bf01-289fdad9c410
... 

但在本次编译、安装系统使用的Docker容器中(flex-build docker),lsblk -f命令本应正常返回的很多参数均为空,其中包括我们所关心的UUID:

1
2
3
4
5
6
7
8
9
10
$ lsblk -f
NAME        FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT
sda                                          
`-sda1                         151.6G    41% /home/suzuco/mnt
sdb                                          
|-sdb1                          24.7M     0% /mnt/sdb1
|-sdb2                         843.1M    51% /mnt/sdb2
|-sdb3                          24.7M     0% /mnt/sdb3
`-sdb4                          23.2G     9% /mnt/sdb4
... 

根据flex-installer的逻辑,也就不难理解为何没有正确配置boot分区的UUID了。

解决方案

经试验,blkid工具可以更可靠地获得分区的UUID。将flex-installer的第350行改为使用blkid即可:

1
uuid_boot=$(blkid -o value -s UUID $bootdev)

备注

原始故障的现象是不挂载/boot导致找不到内核模块,但并不能(仅)通过/etc/fstab来解决,因为boot.mount的自启动是在自动加载内核模块之前,而/etc/fstab则是在加载内核模块之后,因而还是会影响到设备驱动的加载。