跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • 浅色
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • 深色
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(LCZ-Blue)
  • 不使用皮肤
  • LCZ-Green
  • LCZ-Blue
  • LCZ-Black
折叠
品牌标识

抡锤者

首页 版块 标签
硬件
装备秀
AI 广场 App
  1. 主页
  2. 版块
  3. AI硬件
  4. 让你的NV涡轮卡待机时做一个安静的猛男,抛砖引玉: RTX 4090 48G 魔改卡风扇 30% 最低转速破解实录:免刷写 vBIOS 修改指南

让你的NV涡轮卡待机时做一个安静的猛男,抛砖引玉: RTX 4090 48G 魔改卡风扇 30% 最低转速破解实录:免刷写 vBIOS 修改指南

已定时 已固定 已锁定 已移动 AI硬件
rtx4090bios
5 帖子 3 发布者 102 浏览 2 关注中
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • rich kingR
    rich kingR
    rich king
    编写于 最后由 编辑
    #1

    #让你的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 寄存器锁死",其实它是两层叠加:

    1. 驱动层 30% 手动地板。Afterburner / FanControl / nvfancontrol 全部走 NVAPI 手动模式,NVIDIA 从 Ampere 起把用户可设范围硬编码为 30–100%。这是驱动代码,任何软件都改不动。
    2. 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:

    1. 离线编辑 vBIOS 的风扇表(编辑器自动修复校验和,保留原厂签名——反正不刷);
    2. 把编辑后的镜像通过 Windows 驱动的注册表 override 写入(HKLM\SYSTEM\...\Class\{4d36e968-...}\0006 键下的 vbios 二进制值 + EnableGpuFirmware=0x11);
    3. GPU 设备重启时,驱动让 GSP 固件(GPU 内的 RISC-V 处理器)从注册表加载这份镜像,替代卡上 SPI flash 里的原始 ROM;
    4. 卡上的 flash 全程未被写入,删掉注册表值即刻还原出厂状态。

    前提条件:

    项目 要求 本文实测
    GPU 架构 Turing 及以后(依赖 GSP 固件) Ada AD102 ✅
    驱动版本 ≥ 616.56(Verify 功能需 ≥ 617.42) 617.42 ✅
    管理员权限 需要(写 HKLM + 重启设备) ✅
    Ada 特有 镜像必须重定位进 GSP 的 512 KiB 限制,部分卡会超限失败 506.5 KiB 通过 ✅

    三、准备工具

    1. Vix Editor(离线编辑器,含 CLI):https://github.com/Panchovix/nvidia-vbios-vix-editor/releases → 下载 nvbios.exe
    2. Vix Windows Loader:https://github.com/Panchovix/nvidia-windows-vbios-vix-loader/releases → 下载 vbios-loader.exe
    3. Python 3(用于备份脚本,系统装好即可)
    4. 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 上叠加修改。

    十二、风险与免责

    1. 保修:此操作不写 flash、unload 后不留痕,但确实修改了驱动注册表并重启过设备——严格说没有任何软件手段能承诺 100% 零失保风险。在保用户自行权衡。
    2. NVIDIA 随时可能封堵:这条路依赖驱动的注册表 override 机制(与 mVolt+ 同通道,616.56 驱动已经封过一次 mVolt+ 的功耗路线)。作者原话:"highly feasible NVIDIA patches this out on next drivers"。
    3. 堵转红线:涡轮风扇低于约 28–30% 占空比会堵转,固件检测到转速异常可能拉满风扇或锁频。建议从 25% 开始,出现异响/拉满立即回退。
    4. 散热红线:降转速的前提是散热余量。48G 卡双面 GDDR6X,负载下务必监控显存温度。本次实验卡在 240W 功率墙下满载仅 61–67 °C,余量充足才敢做。
    5. 编辑后的 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。

    1 条回复 最后回复
    1
    • rich kingR
      rich kingR
      rich king
      编写于 最后由 rich king 编辑
      #2

      涡轮卡的使用体验得到极大改善,能小涨一波不?😊

      1 条回复 最后回复
      0
      • XitaX
        XitaX
        Xita
        编写于 最后由 编辑
        #3

        这个实在是太硬核了啊!!!

        1 条回复 最后回复
        0
        • terryT
          terryT
          terry
          易有太极
          编写于 最后由 编辑
          #4

          我的卡玩游戏都没啥噪音,4090D 48G,待机几乎没有声音,原生就这样,我还换过一次。

          油管:https://www.youtube.com/@抡锤者

          rich kingR 1 条回复 最后回复
          0
          • terryT terry

            我的卡玩游戏都没啥噪音,4090D 48G,待机几乎没有声音,原生就这样,我还换过一次。

            rich kingR
            rich kingR
            rich king
            编写于 最后由 编辑
            #5

            @terry 说:

            我的卡玩游戏都没啥噪音,4090D 48G,待机几乎没有声音,原生就这样,我还换过一次。

            夜深人静的时候,主机就在身边,跟原生三风扇的4090卡相比,噪音还是比较明显滴,我用了这个方案后效果立竿见影,您老大概是比较抗造已经习惯了吧,嘿嘿……

            1 条回复 最后回复
            0

            你好!看起来您对这段对话很感兴趣,但您还没有一个账号。

            厌倦了每次访问都刷到同样的帖子?您注册账号后,您下次访问时都将自动回到上次浏览的位置,并可选择接收新回复的通知(通过电子邮件或推送通知)。您还可以收藏帖子、为帖子点赞,以此向其他社区成员表达您的感谢。

            有了你的建议,这篇帖子会更精彩哦 💗

            注册 登录
            回复
            • 在新帖中回复
            登录后回复
            • 从旧到新
            • 从新到旧
            • 最多赞同


            • 登录

            • 登录或注册以进行搜索。
            • 第一个帖子
              最后一个帖子
            0
            • 版块
            • 最新
            • 标签
            • 热门
            • 用户
            • 群组