使用 dracut 生成指定内核版本 initramfs

initramfs-tools 并不支持自定义内核路径(主要是 hook-functions 脚本中涉及到内核模块和固件文件的拷贝都是硬编码的路径)。

尴尬的是,虽然 dracut 支持自定义内核路径,但是 Ubuntu 22.04 当前版本的 dracut 有如下 BUG:

$ apt show dracut
Package: dracut
Version: 051-1

$ sudo dracut -N --kver 5.10.0+ -k kbuilt/lib/modules/5.10.0+ initrd.img
/usr/lib/dracut/dracut-init.sh: line 941: 609007 Segmentation fault      (core dumped)

问题定位如下:

$ sudo dracut -N --kver 5.10.0+ -k kbuilt/lib/modules/5.10.0+ initrd.img --debug --keep 2> x.log 1>&2s

$ export DRACUT_FIRMWARE_PATH=/lib/firmware/updates:/lib/firmware
$ /usr/lib/dracut/dracut-install -D /tmp --kerneldir kbuilt/lib/modules/5.10.0+ -m ipmi-devintf
$ sudo coredumpctl gdb 65200
           PID: 65200 (dracut-install)

结合日志和 gdb 跟踪的信息,可以发现 install_dependent_modulesipmi_devintf.ko 的循环依赖处理出现了问题,导致栈溢出而挂掉:

$ cat kbuilt/lib/modules/5.10.0+/modules.dep
kernel/drivers/char/ipmi/ipmi_devintf.ko: kernel/drivers/char/ipmi/ipmi_msghandler.ko

$ cat kbuilt/lib/modules/5.10.0+/modules.softdep
softdep ipmi_msghandler post: ipmi_devintf

modprobe.d (5) - Linux Man Pages
https://www.systutorials.com/docs/linux/man/5-modprobe.d/

通过如下 --omit-drivers 选项可以临时简单规避,最终命令行如下:

$ sudo dracut -N --kver 5.10.0+ -k kbuilt/lib/modules/5.10.0+ kbuilt/initrd.img \
--omit-drivers ipmi-devintf \
--force-drivers "nls_iso8859-1 usbhid virtio-gpu qxl" \
-f

或者合入如下补丁进行解决:

fix(dracut-install): use stripped kernel module path as hash key
https://github.com/dracutdevs/dracut/pull/1889

此外,命令行里加载 nls_iso8859-1 内核模块(如果是编译成内核模块,则还需要 nls_cp437)是为了避免挂载 /boot/efi 分区失败:

FAT-fs (sda1): IO charset iso8859-1 not found

最后修改于 2022-10-06