GRUB2.16更新了原生的NVMe驱动,但对于部分硬盘(比如SAMSUNG MZVLB512HBJQ-000L2)的读取存在bug,如果grubx64.efi 文件内包含了(注意是包含不是加载)nvme.mod在读取大文件(比如内核和initramfs)时就会导致错误overlong nvme read,因为只要grub能找到原生驱动就不会尝试使用efidisk,导致更新后系统不能正常启动.
这个问题只针对使用grub-mkstandalone生成grubx64.efi 且没有指定--install-modules="<modules>"(缺省包含所有模块) 安装的系统 (grub-install指令默认仅会在grubx64.efi 中包含很少的模块并且使用efidisk) ,除非主动使用了insmod nvme/insmod nativedisk 强制使用原生NVMe驱动.
没有测试读取多大的文件时会出现overlong nvme read,但作为参考,数KB的配置文件基本都没什么问题,但是数十MB的内核和initramfs读取时均出现overlong,推测NVMe模块没有针对部分硬盘正确限制一次读请求的大小,对于我的硬盘,lsblk给出下面结果: (但是根据wiki,这可能不准确)
$ lsblk -td
NAME ALIGNMENT MIN-IO OPT-IO PHY-SEC LOG-SEC ROTA SCHED RQ-SIZE RA WSAME
zram0 0 4096 4096 4096 4096 0 128 0B
nvme0n1 0 512 0 512 512 0 kyber 256 128 0B
这个问题可能容易出现在使用安全启动的系统上(因为必须使用grub-mkstandalone)
可以降级包(比如使用downgrade)到2.14或者增加--install-modules="<needed modules>"排除nvme.mod 解决(或许还有其他办法?)
另外对于安全启动还有一个问题(可能是arch的打包问题?),--sbat /usr/share/grub/sbat.csv参数会报告版本不匹配: (生成的grubx64.efi没有.sbat段)
$ grub-mkstandalone -O x86_64-efi -o grubx64.efi --sbat /usr/share/grub/sbat.csv
grub-mkstandalone: 警告: Global SBAT level 4 in /usr/share/grub/sbat.csv' does not match the build-time Global SBAT level 6.
而且pacman -Qkk检查包没有问题