我手上这张 Arc Pro B50(Battlemage G21)是冲着显存大+支持 Linux 主线 SR-IOV去的, 为了能干掉老掉牙 Tesla P8。
但是到手 还是等了一会,官方更新完 32.0.101.6979 驱动(会自动更新固件)以及 Linux 6.17内核+ 才开启 SR-IOV。(虽然bug一堆)
但是,不对劲的是在 32.0.101.6979 之后的驱动,更新完的固件从 12 掉到了 2。官方论坛工程一问三不知,然后最近宣布只支持 2个 VF (?)。
让AI日了一下,结论是可以一边把固件的 OptionROM Code/Data 升到最新,一边用32.0.101.6979 驱动里固件的 config-data(控制GPU的配置的部分)把 VF 数留在 12。
省流版
一条命令搞定(脚本会自己下载静态 igsc 和那个32.0.101.6979 驱动里固件的 config-data):
# curlbash <(curl -fsSL https://file.homelabproject.cc/d/local/Server/Src/B50/b50-flash-12vf.sh)
# 或者 wgetbash <(wget -qO- https://file.homelabproject.cc/d/local/Server/Src/B50/b50-flash-12vf.sh)⚠️ 警告: 只在我自己的卡上验证过,没经过大规模测试。 它确实是可逆的(随时能刷回其他固件),理论上风险很低;但刷固件这种事永远没有”绝对安全”。 !!!出了问题请自己负责!!! Subsystem不是
8086:1114的卡(比如蓝戟那种 OEM 版,SSID 是1ef7:2522)不要直接用,签名 config-data 是按 SSID 匹配的,刷进去固件也认不出来。
具体思路
VF 数到底存在哪
把两个驱动包里的固件文件扒出来对比(SFX 自解压,RAR5 负载拼在 PE 后面,解开就有 Graphics/ifwi/bmg/ 这一坨),B50 的固件分四块:
fwcode/bmg_g21_fwupdate.bin—— GSC 固件本体(igsc fw)fwdata/...e212_config-data.bin—— config-data,VF 数就在这里(igsc fw-data)opromcode/opromdata—— OPROM 那两块
拿 6979 和 8517 的同一个 e212 config-data 做逐字节 diff,553 个字节不一样。绝大部分是签名和哈希(后面会讲),真正有语义的、跟 VF 相关的就一个字节:
偏移 0x3ea66: 0x0c (12) → 0x02 (2)它躺在一条按设备拼出来的记录里,长这样:
... | 0b | 0c | 2e 00 00 00 | 1411 1411 | 8086 8086 | ... ↑VF ↑子系统ID ↑子系统厂商那个 1411 1411 8086 8086 就是子系统 8086:1114。这条记录是按 PCI 子系统 ID 索引的——固件启动时拿你卡的 SSID 去里面找对应记录,读出 VF 数。后来我顺手扫了一圈手上所有的 config-data,这个规律完全成立:
| VF | 子系统 | 来源 |
|---|---|---|
| 12 | 8086:1114 | B50 参考 6979 |
| 2 | 8086:1114 | B50 参考 8517 |
| 7 | 1849:6024 / 172f:0300 | 各家 B60(ASRock / Sparkle) |
| 4 | 1ef7:2522 | 蓝戟 OEM 整片 IFWI |
所以”砍 VF”就是 Intel(或者 OEM)在 config-data 里把这个字节从 12 改成了 2,别的什么都没变。
Patch 回 12 ?
但是是 config-data 是带 RSA-3072 签名的($MN2 manifest)。
翻了 Intel 开源的 igsc 源码:主机端(就是跑在 CPU 上的 igsc 工具)根本不做任何密码学校验。lib/ 里没有一处 sha/rsa/verify 调用,它只解析头部、比几个明文版本号,然后把原始字节经 HECI 灌给固件。验签是固件干的,在那颗 GSC 的 Loader 里,根公钥的哈希烧在熔丝里。
这意味着:你想灌什么进去,主机端都不拦,但固件 100% 会用熔丝里的根来验。没有 Intel 的私钥,改字节不行。
另外
- 改固件本体跳过验签
固件自己也是签名的,boot ROM 用熔丝根来验,改了它固件起不来,直接变砖。这是”最大破坏”,一票否决。 - 驱动层抬高 VF 数:
sriov_totalvfs是只读的,值来自 PCIe SR-IOV 能力寄存器,而那个寄存器是固件按 config-data 编程的。xe的max_vfs参数只能往下夹、不能往上抬。就算 patch 内核谎报更多 VF,GuC 也不会给它们分配 GGTT/显存/context,出来的是不能用的空壳。
那为什么能单独刷 config-data ?
因为 6979 那份 config-data 本身就是 Intel 签过名的,而且它写的就是 12VF。
问题只剩一个:其实这卡一直都能刷完整的旧固件,但是能不能单独降 config-data
这就得看 igsc 那套版本比较逻辑(Format 2)了。device 上报的和镜像里的几个字段挨个比:
major_version:都是 203- OEM 制造版本:6979 是 31,8517 是 41——Format 2 的规则是”只有相等才拒”,31 ≠ 41
- VCN:相等
- 防回滚 ARB SVN:规则是”镜像 < device 才拒”,两边都是 1, 1 < 1 不成立
结果就是 IGSC_FWDATA_VERSION_ACCEPT,工具放行,固件一验签名是Intel 签的。整个过程完全可逆,想刷回 2VF 把 8517 那份再灌一遍就行。
而且——GSC 固件代码和 OPROM 可以单独升到最新的 8517,VF 那块留着 6979 的。两者互不干扰。所以最终状态是:
GSC FW : BMG__21.1177 (8517 的新代码)config-data: OEM 31 (6979 的 12VF)sriov_totalvfs = 12 ✅实际操作长这样
核心就三步,脚本把这些包了一层(加了一堆边界检查、子系统校验、下载校验、幂等判断而已):
# 刷之前确认状态igsc fw version -d /dev/mei1 # 大于 BMG__21.1162 的任意版本
igsc fw-data version -d /dev/mei1 # 记录一下 OEM Manufacturing Data Version
# 确认一下新固件默认的 VF 数量cat /sys/bus/pci/devices/0000:03:00.0/sriov_totalvfs # 2开刷 12VF 的 config-data
igsc fw-data update -d /dev/mei1 --image b50_config-data_6979.bin --allow-downgrade刷完了 重启一下
igsc fw version -d /dev/mei1 # 仍 BMG__21.1177(主要固件版本是没边的)igsc fw-data version -d /dev/mei1输出是 OEM Manufacturing Data Version: 31 就是对了
也就是 6979 版本的 config-data
检查一下能开的 VF 数量
cat /sys/bus/pci/devices/0000:03:00.0/sriov_totalvfs # 12
# 开一下12vf也是有效的echo 12 > /sys/bus/pci/devices/0000:03:00.0/sriov_numvfs
lspci -nn | grep -i e212输出是VF数量是没问题的
03:00.0 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:00.1 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:00.2 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:00.3 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:00.4 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:00.5 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:00.6 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:00.7 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:01.0 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:01.1 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:01.2 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:01.3 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]03:01.4 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Intel Graphics] [8086:e212]