无 U 盘、无 F12 菜单、无 Windows:纯 Linux 环境下给 Insyde BIOS 刷机的一次完整记录
Writ byxiaoyueyoqwq
环境:Lenovo 昭阳 K4e-ARE / Ryzen 7 4800U / Ubuntu 26.04 / BIOS Issue
起因
这台昭阳 K4e 的 BIOS 停在 2021 年的 FACN29WW (V1.12),联想官网最新已经出到 FACN33WW (V1.16),中间隔了四个版本、三四十个固件 CVE,外加一条"改善 S3 唤醒"的修复——对一个主要靠 S3 睡眠的机器来说值得升。本来还抱着一丝幻想:新版 BIOS 可能会暴露 ACPI _CPC,让 amd_pstate 能跑起来(后来的事情证明这个幻想落空了,那是另一个故事)。
问题在于,这台机器的升级路径被堵得非常死:
- 不支持从 USB 临时启动。不是安全策略的问题——BIOS 里能扫到 A/B 两个引导 U 盘,但按 F12 出来的启动菜单是空的,而且 BIOS 不允许调整启动顺序。WinPE 路线直接判死刑。
- 官方只发 Windows 刷写包。
FACN33WW.exe是个必须在 Windows 里跑的安装器。 fwupd不管这个机型。LVFS 没有收录,本地install-blob/local-install也处理不了它的镜像格式。
三个常规路线全断。但 Windows 刷写器的工作方式给了线索:它大概率不是在 Windows 里直接刷 SPI,而是把镜像"暂存"到 ESP,重启后由固件自己完成刷写。如果真是这样,这个"暂存"动作在 Linux 下完全可以手工复现。
拆开官方刷写包
FACN33WW.exe 是 Inno Setup 外层包,用 innoextract 解出来(中途需要补几个 Boost 库),里面才是真正的刷写器套件:
FLV3A033_16M.bin # 18.5MB 固件镜像本体
H2OFFT-Wx64.exe # Insyde Windows 刷写器
H2OFFT64.sys # 内核驱动(负责 SMI 触发)
platform.ini # 刷写配置
镜像开头能看到 $_IFLASH 签名——这是 Insyde 的私有 IHISI/Secure Flash 容器格式,不是标准 UEFI Capsule,所以 fwupd 走不通是确定的。
platform.ini 里有一行关键配置:
[SecureUpdate]
viaESP=3
再 strings 一下 H2OFFT-Wx64.exe,能找到硬编码的路径 EFI\Insyde 和 isflash.bin。拼起来真相大白:这个平台的官方刷写机制就是"把镜像放到 ESP:\EFI\Insyde\isflash.bin,重启后由 BIOS 自己读取、校验、刷入"。Windows 那一套 exe+sys 干的核心工作就是复制文件+通过 SMI 置一个"武装"标志位。
尝试一:直接放文件等固件来取
ESP 有 1G 空闲,直接把镜像放过去:
sudo mkdir -p /boot/efi/EFI/Insyde
sudo cp FLV3A033_16M.bin /boot/efi/EFI/Insyde/isflash.bin
sync
重启。进系统,bios_version 还是 FACN29WW,文件原地没动——固件根本没来扫描。
说明这台机器不是"开机自动扫文件",而是要求先置触发标志位再扫描。Windows 下这个标志是 H2OFFT64.sys 驱动通过 SMI 置上的,Linux 没有等价入口。好在检查 efivar 发现机器上存在 SecureFlashInfo 变量——Insyde SecureFlash 的功能变量,证明当前固件本身就支持这套机制,只是需要换一种触发方式。
尝试二:Insyde 官方 EFI 刷写器
Windows 用不了的工具,UEFI 环境可以。Insyde 有一个 EFI 版刷写器 H2OFFT-Sx64.efi,Framework 笔记本(同样 Insyde 方案)的官方 BIOS 包里就带着它——下载 fw_efi.zip,校验 SHA256,提取出来。虽然它来自别家厂商的发行包,但刷写的是我们自己机器的官方镜像,工具只负责执行 IHISI 协议。
启动方式也用不到 U 盘:efibootmgr 加一次性启动项(BootNext),重启自动进它。
sudo efibootmgr -c -d /dev/nvme0n1 -p 1 -L InsydeFlash -l '\EFI\Insyde\shimx64.efi'
sudo efibootmgr -n 0003
第一个坑:Secure Boot 信任链
H2OFFT-Sx64.efi 是 Framework 自签的,机器的 Secure Boot db 不认。裸 BootNext 它必死。
解法是让微软签名的 Ubuntu shimx64.efi 先起来,再用我们自己 enrolled 的 MOK(之前给自编译休眠内核签名用的 "Secure Hibernate Kernel Project" 证书)给刷写器签名,伪装成 grubx64.efi 让 shim 加载——shim 校验签名通过就会执行。MOK 路径不需要注册新密钥、不需要进蓝屏 MokManager 确认,理论上最干净:
sbsign --key MOK.priv --cert MOK.pem \
--output grubx64.efi H2OFFT-Sx64.efi
ESP 最终布局:
EFI\Insyde\
├── shimx64.efi # Ubuntu shim,微软签名 → 过 Secure Boot
├── mmx64.efi # MokManager,备用
├── grubx64.efi # 实际是签过名的 H2OFFT-Sx64.efi
└── isflash.bin # 固件镜像
第二个坑:MokManager 的 "Enroll Failed"
第一次重启没进刷写器,而是进了蓝黑的 MokManager 界面,报 "Enroll Failed"。
排查发现罪魁祸首是之前一次失败的 mokutil --import-hash 留下的畸形 MokNew 挂起请求:--list-new 都解析不出它,但 shim 认。shim 检测到挂起请求就拐进 MokManager,处理失败报错,然后继续走正常启动。也就是说 shim 链条本身没问题,grubx64.efi 还没轮到出场。
那笔脏数据被消费清空后(EFI 变量确认无残留),重挂 BootNext 再试。
第三个坑:shim 的 SBAT 检查
第二次重启又进了 MokManager。这次不是脏数据——是 shim 拒绝加载 grubx64.efi 后按设计回退到 MOK 管理界面。新版 shim 要求二级启动文件带 .sbat 安全元数据段,这个 Insyde 工具没有,被策略拦下。
MOK 签名本身没问题(我们的自编译内核用同一张证书过 shim 验证),是 SBAT 这一关绕不过去。与其继续斗 shim,不如直接进 BIOS 关掉 Secure Boot——反正 BIOS 更新后设置会重置,刷完再开回来顺手。
第四个坑:Password check failed
Secure Boot 关掉后链条终于跑通:shim → grubx64.efi → 刷写器启动 → 然后报 Update device firmware failed!,一闪而过看不清细节。
从 H2OFFT-Sx64.efi 的字符串里能翻出完整的错误列表:Power check failed、Password check failed、BIOS IHISI version too old、Secure Boot Protection check failed……其中最有嫌疑的是密码——这台机器设着 Supervisor Password,而 Insyde 刷写器会拒绝在有管理员密码的固件上执行刷写。
进 BIOS 把 Supervisor Password 设为空,保存退出。
最终方案:EFI Shell 里手动执行
盲试阶段结束,改成可控环境:放一个 Shell_Full.efi(EDK2 全功能 Shell,同样从 Framework 包里拿的)到 ESP,BootNext 指过去,进 Shell 手动跑刷写器,所有报错都能看清、可以反复试。
sudo efibootmgr -c -d /dev/nvme0n1 -p 1 -L EFIShell -l '\EFI\Insyde\Shell_Full.efi'
sudo efibootmgr -n 0006
第五个坑:Shell 的 "Current dir not specified"
进了 Shell 直接敲 H2OFFT-Sx64.efi isflash.bin,报 Current dir not specified——Shell 还没挂载/选定文件系统。需要先:
Shell> map -r # 重新枚举文件系统
Shell> map # 列出 FS0、FS1……找到那个 ~1G 的 FAT32(就是 ESP)
Shell> fs0: # 切过去(编号以 map 输出为准)
Shell> ls \EFI\Insyde
Shell> cd \EFI\Insyde
另一个小插曲:中途看到的 img not support / StartImage() failed 其实是错误路径下找不到/读不了镜像的连锁报错,不代表镜像本身有问题——在同一目录下用相对路径调用就没这事了。
成功
fs0:\EFI\Insyde> H2OFFT-Sx64.efi isflash.bin
刷写器这次一路走下去:校验镜像 → 显示刷写进度 → 自动重启。进系统:
$ cat /sys/class/dmi/id/bios_version
FACN33WW(V1.16)
收尾工作
- 清理 ESP:
rm -rf /boot/efi/EFI/Insyde(含镜像、刷写器、Shell、shim 全套) - 删启动项:
efibootmgr -b 0003 -B、-b 0006 -B,BootOrder 恢复原样 - 回 BIOS 设置:重新打开 Secure Boot、重设 Supervisor Password
- LUKS 是 TPM 绑定的(
tpm2-device=auto)——实测这次更新后 TPM 自动解锁仍然正常,但这是个需要备着 LUKS 密码的已知风险点;如果失效,systemd-cryptenroll重新绑定即可 - 遗留结论:新 BIOS 依然没有
_CPC,amd_pstate在这台机器上确认不存在——AMD 官方建议 OEM 不要在 Renoir 这一代启用 CPPC,联想 trial BIOS 都测出来了也没放行。这次更新拿到的实际收益是 CVE 修复和 S3 改善。
完整失败链路回顾
| 尝试 | 结果 | 原因 |
|---|---|---|
| fwupd / LVFS | 不可行 | 机型未收录,且镜像是 Insyde $_IFLASH 私有格式非标准 Capsule |
ESP 放 isflash.bin 直接重启 | 固件无视 | 需要 SMI 武装标志位才扫描 |
| shim + MOK 签名链第一次启动 | MokManager Enroll Failed | 早前 --import-hash 失败残留畸形 MokNew 请求 |
| shim + MOK 签名链第二次启动 | 回退 MokManager | shim SBAT 策略拒绝无 .sbat 段的二级 EFI |
| 关 SB 后直接启动刷写器 | Update BIOS Failed | BIOS 设着 Supervisor Password |
| EFI Shell 直接跑命令 | Current dir not specified | 未选定 ESP 文件系统卷 |
| Shell 内正确路径执行 | 成功 | 全部前置条件清除 |
总结几个关键
- Insyde 机器的核心情报在
platform.ini和刷写器字符串里:viaESP、isflash.bin、EFI\Insyde这些约定都是二进制里翻出来的,不需要逆向。 H2OFFT-Sx64.efi是通用工具,Framework 的包只是最方便的获取渠道;它刷的是你自己的镜像,不存在混刷问题(Insyde SecureFlash 会先校验签名和平台,不匹配会拒绝)。- BootNext 一次性启动项完全替代 F12 菜单和 U 盘,这是 USB 启动被废掉时的通用逃生通道,不限于刷 BIOS。
- 检查顺序:Secure Boot → MOK/SBAT → Supervisor Password → Shell 的 fsX 挂载。我们按反向顺序踩了每一个坑。
- 风险:全程插电;BIOS 设置会重置;TPM 绑定的 LUKS 备好恢复密码。镜像校验由固件自己做,放错文件最坏结果是被无视,不会半刷。
Finis.