让你的NV涡轮卡待机时做一个安静的猛男,抛砖引玉: RTX 4090 48G 魔改卡风扇 30% 最低转速破解实录:免刷写 vBIOS 修改指南
-
#让你的NV涡轮卡待机时做一个安静的猛男,抛砖引玉: RTX 4090 48G 魔改卡风扇 30% 最低转速破解实录:免刷写 vBIOS 修改指南
一句话总结:不需要刷写任何 flash,通过官方开源工具链修改 vBIOS 风扇表并经驱动注册表加载,48G 魔改卡的怠速风扇转速从 2000 RPM 降到 1500 RPM(约 -25% 转速、声功率降至 42%),负载曲线完全正常,随时可一键还原。
本文以 RTX 4090 48G(AD102,vBIOS 95.02.3C.00.02,驱动 617.42)实测通过。方法基于 Panchovix 的开源 Vix 工具链,理论上适用于"被 vBIOS 锁最低转速"的 Turing 及以后的 NVIDIA 卡(Ampere/Ada/Blackwell 风扇表结构同版本),但除本文实测的 48G 卡外未验证。
一、背景:这个"30%"到底锁在哪
很多人以为 30% 是"vBIOS 寄存器锁死",其实它是两层叠加:
- 驱动层 30% 手动地板。Afterburner / FanControl / nvfancontrol 全部走 NVAPI 手动模式,NVIDIA 从 Ampere 起把用户可设范围硬编码为 30–100%。这是驱动代码,任何软件都改不动。
- vBIOS 风扇策略表的下限。48G 魔改卡各厂贴的固件不同,有人是 30% 版,有人是 60% 空转写死版。
关键机制(NVIDIA 开发者论坛版主原话):
"The reported fan speed range is what you the user can set, not what VBIOS can set."
即:固件自动模式不受 30% 用户地板限制,它按 vBIOS 曲线表执行。而驱动把"用户手动 30%"映射到 vBIOS 风扇表的最小值(Vix 作者 Panchovix 在 issue #14 的解释)。
所以正确的思路不是"把 30% 地板撬到 10%",而是:修改 vBIOS 风扇表的最小值/曲线起点,让驱动 30% 地板所映射的实际转速变低。
还有两个物理/固件事实要先知道,免得白忙:
- 涡轮鼓风机在约 28–30% 占空比以下会堵转。把下限压得太低,风扇会停转/堵转,固件检测到转速异常可能反而拉满。本次实测 25%(1500 RPM)仍在涡轮正常工作区。
- 低温停转(zero-RPM)在 48G 卡上不可行。这块卡的 vBIOS 里 zero-RPM 标志位出厂就没置位(这正是它怠速常转的根源),编辑器明确拒绝在 Ada 上改这些标志位。本指南只做"降低怠速转速"。
二、为什么是"免刷写"而不是刷 BIOS
Ada(RTX 40 系列)的 vBIOS 签名锁没有被破解——2023 年那波 nvflash 破解只覆盖到 Turing,40 系只能 crossflash(互刷原厂未修改的 BIOS),自己改过内容的 ROM 刷不进去。
Panchovix 的 Vix 工具链绕开了 flash:
- 离线编辑 vBIOS 的风扇表(编辑器自动修复校验和,保留原厂签名——反正不刷);
- 把编辑后的镜像通过 Windows 驱动的注册表 override 写入(
HKLM\SYSTEM\...\Class\{4d36e968-...}\0006键下的vbios二进制值 +EnableGpuFirmware=0x11); - GPU 设备重启时,驱动让 GSP 固件(GPU 内的 RISC-V 处理器)从注册表加载这份镜像,替代卡上 SPI flash 里的原始 ROM;
- 卡上的 flash 全程未被写入,删掉注册表值即刻还原出厂状态。
前提条件:
项目 要求 本文实测 GPU 架构 Turing 及以后(依赖 GSP 固件) Ada AD102 
驱动版本 ≥ 616.56(Verify 功能需 ≥ 617.42) 617.42 
管理员权限 需要(写 HKLM + 重启设备) 
Ada 特有 镜像必须重定位进 GSP 的 512 KiB 限制,部分卡会超限失败 506.5 KiB 通过 
三、准备工具
- Vix Editor(离线编辑器,含 CLI):https://github.com/Panchovix/nvidia-vbios-vix-editor/releases → 下载
nvbios.exe - Vix Windows Loader:https://github.com/Panchovix/nvidia-windows-vbios-vix-loader/releases → 下载
vbios-loader.exe - Python 3(用于备份脚本,系统装好即可)
- FanControl 或 GPU-Z(验证真实转速用;nvidia-smi 的百分比读数会失效,下文解释)
安全提示:两个 exe 均有官方 SHA256SUMS,下载后核对哈希。GUI 版(nvbios-gui.exe / vbios-loader-gui.exe)可能被 Windows Defender 报未签名警告,CLI 版实测干净,本文全程用 CLI。
四、Step 0:备份你的原厂 vBIOS
这一步是整个流程的安全网,绝对不要跳过。
两种方式任选:
方式 A:GPU-Z(适合所有用户)
打开 GPU-Z → 右下角
Save BIOS→ 存为48G_backup.rom。方式 B:NVAPI 直接读(免装任何东西,本文所用)
驱动的 NVAPI 接口能读出 GSP 正在运行的完整 vBIOS 镜像(无 override 时即卡上原厂镜像),需要驱动 ≥ 617.42。把下面脚本存为
dump_vbios.py:"""通过 NVAPI 读出当前 GPU 正在运行的 VBIOS 镜像。只读操作。""" import ctypes, os, sys IMAGE_SIZE = 0xFA000 IMAGE_VERSION = 0x00020010 MAX_PHYSICAL_GPUS = 64 OK, NO_IMPLEMENTATION = 0, -3 OUT = sys.argv[1] if len(sys.argv) > 1 else "vbios_backup.rom" LOCATION = sys.argv[2] if len(sys.argv) > 2 else "01:00.0" # PCI 位置 bb:dd.f,nvidia-smi 可查 class NV_GPU_VBIOS_IMAGE(ctypes.Structure): _fields_ = [("version", ctypes.c_uint32), ("size", ctypes.c_uint32), ("buffer", ctypes.c_void_p)] _U32 = ctypes.POINTER(ctypes.c_uint32) FUNCTIONS = { "Initialize": (0x0150E828, ctypes.CFUNCTYPE(ctypes.c_int)), "Unload": (0xD22BDD7E, ctypes.CFUNCTYPE(ctypes.c_int)), "GetErrorMessage": (0x6C2D048C, ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_char))), "EnumPhysicalGPUs": (0xE5AC921F, ctypes.CFUNCTYPE(ctypes.c_int, ctypes.POINTER(ctypes.c_void_p), _U32)), "GPU_GetBusId": (0x1BE0B8E5, ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, _U32)), "GPU_GetBusSlotId": (0x2A0A350F, ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, _U32)), "GPU_GetVbiosImage":(0xFC13EE11, ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.POINTER(NV_GPU_VBIOS_IMAGE))), } query = ctypes.WinDLL(os.path.join(os.environ.get("SystemRoot", r"C:\Windows"), "System32", "nvapi64.dll")).nvapi_QueryInterface query.restype, query.argtypes = ctypes.c_void_p, [ctypes.c_uint32] def fn(name): fid, proto = FUNCTIONS[name] addr = query(fid) if not addr: raise OSError(f"driver has no NvAPI_{name} (needs 617.42+)") return proto(addr) def call(name, *args): st = fn(name)(*args) if st == NO_IMPLEMENTATION: raise OSError(f"NvAPI_{name}: no implementation") if st != OK: raise OSError(f"NvAPI_{name} failed: status {st}") bus, dev = int(LOCATION[:2], 16), int(LOCATION[3:5], 16) handles, count = (ctypes.c_void_p * MAX_PHYSICAL_GPUS)(), ctypes.c_uint32() call("Initialize") try: call("EnumPhysicalGPUs", handles, ctypes.byref(count)) m = [] for h in handles[:count.value]: b, d = ctypes.c_uint32(), ctypes.c_uint32() if fn("GPU_GetBusId")(h, ctypes.byref(b)) == OK and fn("GPU_GetBusSlotId")(h, ctypes.byref(d)) == OK: if (b.value, d.value) == (bus, dev): m.append(h) if len(m) != 1: raise OSError(f"no unique GPU at {LOCATION}") buf = ctypes.create_string_buffer(IMAGE_SIZE) req = NV_GPU_VBIOS_IMAGE(IMAGE_VERSION, IMAGE_SIZE, ctypes.addressof(buf)) call("GPU_GetVbiosImage", m[0], ctypes.byref(req)) data = buf.raw[:req.size] finally: try: fn("Unload")() except OSError: pass open(OUT, "wb").write(data) print(f"saved {len(data)} bytes -> {OUT}; head={data[:4].hex()}")运行(PCI 位置用
nvidia-smi里 Bus-Id 的后段,如00000000:01:00.0→01:00.0):python dump_vbios.py 48G_backup.rom 01:00.0校验:用编辑器确认版本与卡上一致——
nvbios inspect 48G_backup.rom输出里的
versions应该和nvidia-smi --query-gpu=vbios_version --format=csv完全一致。五、Step 1:查看风扇字段(离线,零风险)
nvbios fields 48G_backup.rom关注这几个字段(以 48G 卡实测为例):
fan_1_min_pct cur=30 % → 可编辑,下限 0 fan_1_min_rpm cur=2000 RPM → 可编辑,下限 0 fan_1_curve_1_pct cur=30 % → 可编辑(需与 min_pct 同一次编辑联动) fan_1_curve_1_rpm cur=2000 RPM → 可编辑(同上) fan_2_* (第二通道,涡轮卡通常与通道 1 一致,改法相同) fan_N_zero_rpm_* → 48G 卡显示 read-only(zero-RPM 标志位出厂未置位)风扇策略的结构:固件在温度低于曲线点 1 时执行曲线起点(= min)。怠速 30% / 2000 RPM 的真身就是这个起点。
如果
fields报错或大面积 "layout not supported",说明你的 vBIOS 布局暂不被编辑器支持,流程到此为止(不影响系统)。六、Step 2:编辑风扇表
以"怠速 30%/2000 RPM → 25%/1500 RPM"为例(25% 是涡轮堵转约束下的保守第一档,不建议一次压更低)。所有值必须在同一次编辑里写入(编辑器要求 min 与曲线点联动)。命令较长,这里写成一行(cmd / PowerShell 通用):
nvbios edit 48G_backup.rom edited.rom --set fan_1_min_pct=25 --set fan_1_min_rpm=1500 --set fan_1_curve_1_pct=25 --set fan_1_curve_1_rpm=1500 --set fan_2_min_pct=25 --set fan_2_min_rpm=1500 --set fan_2_curve_1_pct=25 --set fan_2_curve_1_rpm=1500编辑器会输出 manifest(
edited.rom.json),确认edits列表里 8 项全部命中、changed_bytes很小(48G 卡实测 13 字节)、integrity.valid = true。再跑一次完整性验证:
nvbios verify edited.rom七、Step 3:生成 Ada loader payload
Ada 的 GSP 固件只读 512 KiB,必须把镜像重定位压缩:
nvbios normalize edited.rom payload.bin --representation ada-relocated-v2成功会输出
"ok": true并生成payload.bin。这一步是最常见的失败点——部分 Ada 卡的表格塞不进 512 KiB 会报RELOCATION_DOES_NOT_FIT。48G 卡实测 506.5 KiB,通过。八、Step 4:加载(需要管理员 + 重启 GPU 设备)
以管理员运行(PowerShell 管理员窗口,或右键批处理):
vbios-loader load payload.bin --pci 01:00.0它做的事:写注册表 override →
pnputil重启 GPU 设备。注意:- 显存里的分配会被清空(有 CUDA 负载先停掉);
- 功率墙会被重置回默认(如之前
nvidia-smi -pl设过的话),加载完必须重设; - 该卡无显示输出时不会黑屏;如果这张卡接着显示器,参考 loader 文档(建议直接重启系统)。
九、Step 5:验证
vbios-loader verify应输出 "The driver is using the stored override (verified byte by byte)"——驱动 GSP 正在运行的镜像与你的编辑版逐字节一致。
然后看实际效果。注意:
nvidia-smi --query-gpu=fan.speed的百分比读数此时失去参考意义——它报告的是"用户档位空间"的位置(30% 地板档),不是物理占空比。真实转速请看:- FanControl / GPU-Z 读 tach RPM(本文实测:怠速 2000 → 1500 RPM);
- 或者最直接的:耳朵。声功率降到约 42%((1500/2000)³ ≈ 0.42),差异明显。
必须做的负载测试:跑一个满载(炼丹/游戏/stress),确认风扇仍随温度正常加速、无卡死、无异响、无保护性拉满。本文实测:57 °C→31%、64 °C→50%、67 °C→56%,响应正常。48G 卡负载时记得盯显存温度(
nvidia-smi -q -d TEMPERATURE)——双面 GDDR6X 靠涡轮风道散热,别只看核心温度。最后:
nvidia-smi -pl 240(按你自己的功率墙习惯重设)。十、实测数据汇总
项 改动前 改动后 怠速真实转速(tach 实测) ~2000 RPM ~1500 RPM nvidia-smi 报告 30% 30%(档位名,不再代表物理占空比) 负载曲线 56/61/69 °C → 2000/4000/6000 RPM 起点降为 1500,中后段逐字节不变 卡上 flash — 全程未被触碰 原理回顾:驱动把"手动 30%"映射到 vBIOS 风扇表最小值。min 从 30%/2000 降到 25%/1500 后,映射目标随之降低,而 NVAPI 的 30–100 档位范围不变——所以显示 30%、实际转 1500。
十一、回退方法
一键回退(管理员):
vbios-loader unload删除 override、恢复原
EnableGpuFirmware、重启设备,即刻回到出厂状态。别忘了重设功率墙。日常维护:
- 驱动更新后 override 可能丢失:跑
vbios-loader verify,若显示 override 不在,重新load即可; - 想换别的转速值:从
48G_backup.rom(原厂备份)重新走 Step 2–4,不要在 edited.rom 上叠加修改。
十二、风险与免责
- 保修:此操作不写 flash、unload 后不留痕,但确实修改了驱动注册表并重启过设备——严格说没有任何软件手段能承诺 100% 零失保风险。在保用户自行权衡。
- NVIDIA 随时可能封堵:这条路依赖驱动的注册表 override 机制(与 mVolt+ 同通道,616.56 驱动已经封过一次 mVolt+ 的功耗路线)。作者原话:"highly feasible NVIDIA patches this out on next drivers"。
- 堵转红线:涡轮风扇低于约 28–30% 占空比会堵转,固件检测到转速异常可能拉满风扇或锁频。建议从 25% 开始,出现异响/拉满立即回退。
- 散热红线:降转速的前提是散热余量。48G 卡双面 GDDR6X,负载下务必监控显存温度。本次实验卡在 240W 功率墙下满载仅 61–67 °C,余量充足才敢做。
- 编辑后的 ROM 永远不要用 nvflash 刷进卡里(原厂签名已不匹配,且没必要)。
十三、致谢与参考
- Panchovix/nvidia-vbios-vix-editor 与 nvidia-windows-vbios-vix-loader——本文所有核心能力都来自这个开源工具链
- extended-fields.md——风扇表偏移与字段语义的技术文档
- issue #12(5080 上同类实验:改 zero-RPM 阈值成功、降 min 失败)、issue #14(作者解释 30%
fan minimum 映射) - TechPowerUp 报道
- NVIDIA 开发者论坛:30% 地板讨论
- NVAPI 备份脚本的实现参考自 Vix loader 的 nvapi.py(MIT)
实测环境:RTX 4090 48G 魔改卡(10DE:2684 SUBSYS 16F3),vBIOS 95.02.3C.00.02,Windows 11 24H2,驱动 617.42,240W 功率墙。2026-10。
-
-
-
-
