ARM 平台也能改 BIOS 隐藏项了——gsetupmod 双架构发布这几年玩固件调试的朋友应该都有一个共同感受x86 平台想解锁 BIOS 隐藏项、打开被厂商屏蔽的 Advanced 菜单手段已经非常成熟工具链也齐全搜一搜就能找到一大堆教程。但一旦换到 ARM 平台的板子、迷你主机、笔记本或者服务器主控事情立刻就变得很麻烦。UEFI 规范明明在 ARM 和 x86 上都是同一套框架实际动起手来却处处碰壁——EFI Shell 下能用的脚本少、变量读写工具不通用、固件模块结构差异又大很多人试到一半就放弃了。这篇文章要聊的 gsetupmod正好补上了这个缺口。它的思路和 x86 上常见的 GRUB Shell 变量修改法有相似之处但针对 ARM 平台重新设计了模块解析和变量定位逻辑同时在双架构下发布x86 和 ARM64 的固件都能覆盖到。适合谁看如果你手上有 ARM 平台的开发板、工控机、NAS 主控板或者只是想搞清楚 UEFI Setup 隐藏项到底是怎么被“藏”起来的那么这篇文章能帮你少走不少弯路。我会从原理开始讲再给出一套可以照着做的实操流程最后把容易踩的坑一并整理出来。1. 为什么 ARM 平台改 BIOS 隐藏项比 x86 难这么多1.1 传统固件调试工具几乎都是 x86 的“专属玩具”先看 x86 平台为什么好折腾。UEFI 固件从设计上说核心调度逻辑DXE 阶段、BDS 阶段是由 PI 规范统一的不管是 Intel 还是 AMD 的平台只要遵循 PI 规范固件内部结构就大差不差。于是那些经典工具——UEFITool、IFRExtractor、RU.efi、GRUB Shell 里的 setup_var全部在这个统一的框架下工作得很好。你会看到很多人用一条 GRUB 命令就能改变量值、解开隐藏菜单本质上是绕过了 BIOS Setup 页面的图形界面直接去操作固件中的 UEFI 非易失性变量。但这个生态有个隐含前提早期的 UEFI 实践主要围绕 x86 展开。x86 平台从 BIOS 过渡到 UEFI 的时间早厂商投入大工具链自然最完善。ARM 平台虽然也跑 UEFI可真正大规模落地是近几年的事很多工具根本没有 ARM64 版本或者即使能编译跑起来也会因为固件实现差异而失灵。比如 RU.efi 这种经典的变量查看修改工具在部分 ARM 机器上连加载都困难更别提去解析 IFR 数据了。1.2 ARM 平台有自己的“方言”不是简单换一个 CPU 架构ARM 平台难改不仅是因为工具少更深层的原因是固件实现的碎片化。x86 平台有比较统一的 PC 兼容层主板厂商在 UEFI 上做差异化更多是围绕菜单选项、默认策略、板载外设来展开底层框架差异有限。ARM 平台则不太一样同样是跑 UEFI服务器板卡、消费级 ARM 笔记本、嵌入式核心板、网络设备主控板它们的固件来源各不相同有的基于 EDK2 官方主干有的用 Linaro 分支还有的直接拿芯片厂商 SDK 改隐藏项的实现方式非常多样。这就带来一个很现实的问题你在 x86 上只需要“找到变量名、修改变量值、重启”三步在 ARM 平台上可能需要先花大量时间搞清楚固件用的是哪一套 HII 配置、隐藏项是被哪个条件变量控制的、变量 GUID 是否被厂商改过。很多人入手 ARM 平台后第一反应是“怎么资料这么少”其实不是资料少而是每一家的实现都不一样很难写出一份通用的教程。gsetupmod 这次双架构发布最实际的意义是提供了一个能解析常见 ARM UEFI 固件模块、定位并修改隐藏 Setup 项的工具把碎片化程度降低了一点。2. 隐藏选项到底是怎么来的先搞懂 UEFI Setup 的底层逻辑2.1 你看到的每一个 BIOS 设置项本质上都是一段 IFR 数据要做 BIOS 隐藏项修改第一步不是拿工具去改而是先弄清楚你改的是什么。UEFI Setup 页面并不是一个简单的“图形界面配置文件”它由一组 DXE 驱动在运行时动态生成这些驱动通过 HIIHuman Interface Infrastructure数据库对外提供表单。每个页面上的每一项——不管是下拉框、复选框还是数值输入框在固件编译时都是由 VFR 源文件描述再被编译成 IFR 二进制数据。IFR 的实质是类似脚本的解释执行代码。一个下拉框选项OneOf、一个开关选项CheckBox、一个数值输入框Numeric在 IFR 数据里都有对应的 opcode。HII 数据库在启动阶段读取这些 opcode按规则来绘制界面同时把设定值保存到 UEFI 非易失性变量中。也就是说你在 BIOS 设置页面里看到的每一个选项背后都有一个变量和它对应。改隐藏项的本质要么是直接把这个选项从“隐藏”状态改成“显示”状态要么是绕过界面直接写入对应变量的值。这里有一个很多教程没讲透的点隐藏项并不一定需要修改二进制代码才能显示出来。很多隐藏项只是被一个条件变量或一个 PCD平台配置数据库开关控制着只要让条件成立菜单就自动出现了。gsetupmod 的核心工作其实就是站在 HII 数据库的角度去“问”固件你有哪几个页面、哪几个选项、每个选项由哪个变量控制然后根据你指定的条件去修改这个变量的值。2.2 厂商为什么要把某些选项藏起来了解厂商的“藏”法有助于判断哪些选项值得解锁。不同厂商隐藏选项的原因各不相同大致能归成三类。第一类是工厂调试项比如内存电压微调、PLL 配置、总线时序参数这些在量产阶段用于调校硬件正常用户不需要碰打开之后误操作还可能损坏设备所以厂商默认隐藏。第二类是兼容性选项比如某些 ARM 主板对 PCIe 链路速度、USB 协议模式做了限定正常固件版本里不给用户修改入口但调试时确实需要调整这类隐藏项解锁之后非常实用。第三类是软开关项常见的如制造模式、调试日志开关、安全启动策略的额外控制位它们往往不是为了给用户用而是为了方便开发维护人员在工厂或售后环境里做诊断。理解这一点后你在决定要改哪些选项时就能更有针对性。盲目打开所有隐藏项不是好习惯有些工厂调试项一旦改了错误的值轻则系统不稳定重则设备启动异常。比较务实的做法是先锁定你要解决的问题再找到对应的菜单或变量小范围修改。2.3 gsetupmod 的工作逻辑解析、定位、修改gsetupmod 的工作流程可以拆成几个动作。它会先从固件映像中识别出负责 Setup 页面的 DXE 驱动模块再从驱动模块中提取 IFR 数据。拿到数据之后工具会建立一份“隐藏选项清单”列出每个选项的变量名、变量 GUID、偏移量和可能的取值集合。你用交互界面或者命令行参数选中目标选项后工具把它转化为实际的 UEFI 变量写入操作说白了就是直接写到你固件里的某个变量区域。在 x86 平台上类似的思路通常用 GRUB Shell 的 setup_var 系列脚本实现但 GRUB Shell 在 ARM 平台的可用性很不稳定还需要单独适配。gsetupmod 之所以能做双架构关键在于它把 IFR 解析和变量写入两个环节完全解耦了——解析环节面向 EDK2 固件共同的数据格式相对通用写入环节则根据运行时环境自动切换到对应的架构实现。这算是碰到 ARM 平台碎片化之后比较务实的工程解法效果我用下来也确实不错。3. gsetupmod 双架构实操从提取固件到点亮隐藏菜单3.1 工具选型的几个选项为什么我推荐直接试 gsetupmod在 gsetupmod 出现之前ARM 平台改 BIOS 隐藏项并不是完全没有办法只是各有各的痛点。我整理了一下现状供大家对比参考。方案平台适配上手难度主要问题直接二进制 patch 固件模块理论通用很高需要反汇编能力不同固件差异大一个字节偏移算错就变砖GRUB Shell 变量修改法x86 比较稳ARM 很不稳定中等ARM 设备加载 GRUB 麻烦变量偏移需要手查效率低自己写 EDK2 应用通用但需要编译环境很高开发周期长对新手不友好光搭交叉编译环境就够折腾gsetupmodx86 / ARM64 通用性好低到中等项目比较新资料还在积累中但基本流程已经可用从我试过的情况来看如果你是第一次在 ARM 平台上做隐藏项修改gsetupmod 是最不容易卡住的选择。它不需要你熟悉 ARM 汇编也不需要你手动反编译固件模块工具会把 IFR 里的选项直接列出来你只需要知道你想打开哪个选项就行。而且它对常见 EDK2 固件的解析成功率高省去了不少前期摸索的时间。3.2 第一步提取当前固件确认架构与模块位置不管用什么工具改 BIOS 之前先备份当前固件永远是第一步这在 ARM 平台尤其重要。部分 ARM 开发板的 SPI Flash 是直接焊在板子上的一旦刷入错误的固件恢复比 x86 平台麻烦得多。备份的方式取决于你的设备类型。如果你的板子能在 UEFI Shell 下操作可以尝试用 Shell 下的固件备份命令直接导出一份完整固件如果设备使用标准的 UEFI Capsule 更新机制也可以尝试通过主板厂商提供的刷机工具备份最直接的办法是查阅你的板卡用户手册看有没有官方提供固件备份命令或工具。拿到固件之后建议先用 UEFITool 或者类似工具确认固件的基本信息。这里要注意如果你的固件包是拆包后的单个模块需要先辨认它属于哪一类模块。负责 Setup 页面的模块通常是 UiApp 或者 Setup 相关的 DXE 驱动文件名可能包含 Setup、Hii、Menu 之类的字样。在 ARM 平台这个模块可能会出现在不同于 x86 的 FVFirmware Volume分区里搜索时需要耐心一点。如果你在固件包中看到了 DXE 驱动列表不妨先把与 Setup、Hii 相关的模块全部导出备着后续解析用得上。这一步其实能过滤掉很多风险。如果固件模块导不出来说明你的固件可能做了封装或者加密这种加密固件后续所有修改都可能无效早点发现比刷坏之后才意识到要好得多。3.3 第二步运行 gsetupmod选择目标模块和变量环境准备好之后就可以开始实际操作了。这里以我调试的一块 ARM 开发板为例说明整个过程。首先是获取固件模块。把上一步用 UEFITool 导出或者从备份工具中提取的 Setup 模块放到工作目录。然后运行 gsetupmod进入交互模式。工具启动后会扫描指定模块并把其中包含的所有 IFR 选项以列表形式打印出来。我在实际使用中发现ARM 固件的模块命名有时候没有 x86 那么直观建议在列表里先按“变量名”排序而不是按“选项名”排序因为有些隐藏项的名称非常笼统靠变量名定位更快。定位到目标选项后下一步是查看它支持的所有取值。这一步非常关键。以常见的 DVMT 预分配显存或 PCIe 速度控制为例同样一个功能在不同固件里可能支持不同的值域比如“Auto / 1G / 2G”和“Auto / 512M / 1G / 2G”就完全不同。确认好取值后选择设置目标值。gsetupmod 在写入变量前通常会让你二次确认变量名、GUID 和最终值这一步不要跳过仔细看一看避免写错地方。写入完成后工具会在当前会话中更新变量但有些固件环境下变量写入后并不会立刻反映到当前 Setup 页面需要重启才会重新加载。也有个别板子的固件实现比较特殊修改后的变量在启动流程中被固件逻辑再次覆盖这类我在下一节专门说。3.4 第三步重启验证以及无效时的回退思路重启进入 BIOS 设置界面后先对照你刚才修改的选项确认隐藏菜单是否出现、值是否和设定一致。这里有一个经验有时候菜单没出现不一定是写入失败而是因为隐藏菜单被多个条件同时控制。比如某个 Advanced 子页面需要在“主开关”和“子开关”两个变量都为特定值时才会显示。你只改了一个自然看不到效果。如果修改后无效我的建议是先别着急重新刷固件。进入 Shell 环境用 gsetupmod 的查询功能把目标变量的当前值读出来和写入值做对比。如果变量根本没有被写入多半是变量 GUID 不匹配或者固件有运行时过滤器在拦截写入。如果变量写入了但值被复位多半是固件启动流程中有默认值加载逻辑比如 PEI 阶段的默认配置覆盖了你的修改。这两种情况处理思路完全不同前者要重新确认选项所对应的变量定义后者则需要找更底层的默认值表去改。我自己遇到过一种情况某 ARM 网关系列BIOS 设置里的“串口重定向”选项被隐藏但无论我怎么改变量重启后总是恢复默认值。后来排查发现这个设备的固件在每个启动阶段的早期都会从备份区重新加载一份默认变量你直接改当前活动变量根本挡不住。这种设备就不能靠 gsetupmod 一改了之需要分析固件里默认变量表的存储位置改默认值才能让修改持久生效。换句话说工具能把“改哪里”的问题解决掉但“改完能不能留住”还得看厂家固件的具体实现这一点必须心里有数。4. ARM 平台改 BIOS 最容易踩的坑以及排查清单4.1 签名验证与安全启动的先后问题很多 ARM 设备默认开启 Secure Boot这在修改隐藏项时会带来一个让人头疼的情况即使你成功修改了某个变量重启后固件在验证阶段发现变量区内容与签名记录不一致可能直接丢弃你的配置极端情况下还会触发恢复模式。这不是变量写入失败而是平台的安全策略在起反作用。遇到这种情况建议先进入固件设置界面找到 Secure Boot 相关的启动模式选项切换成自定义模式或者暂时关闭签名验证。要注意部分 ARM 板卡在关闭 Secure Boot 后某些隐藏选项依然受平台信任根保护需要你把平台密钥PK清空后才能正常修改。这个操作有风险清空前务必确认你手里有原始密钥备份否则后续安装某些系统可能会卡在验证环节。4.2 变量存储空间不是无限的UEFI 非易失性变量存储在 SPI Flash 里空间是有限的。x86 平台变量空间通常预留了足够余量但部分 ARM 设备为了削减成本变量存储区设置得比较小。如果你在一个会话中反复修改多个变量或者每次修改都触发固件写入大量日志变量存储空间可能被占满这时候再尝试写入新变量就会失败而且失败日志往往不明显你只会看到“修改之后重启没效果”。排查方法不难。在 gsetupmod 里查询目标变量的大小同时留意当前环境的剩余变量空间。如果剩余空间很少建议只改和你需求最相关的几个选项不要贪多如果空间已经满了需要通过固件自带的重置功能清理冗余变量或者先恢复默认设置给后续修改腾出空间。4.3 不同厂商的变量命名和偏移没有统一规律ARM 平台固件碎片化的问题在变量命名上体现得非常明显。同一个功能Intel 参考实现里可能叫 Setup.DvmtPreAlloc某 ARM 厂商的固件里可能叫 VarSetup.DvmtSize还有的会在 GUID 上做文章直接用私有 GUID。这就意味着网上的现成教程只能作为参考不能直接照抄。你在自己的板子上看到变量列表后最好先用“选项名称”去反查“变量名”确认对应关系再动笔改。关于“D大魔改BIOS”这类词很多朋友可能会想到各种论坛里流传的定制版 BIOS。但说句掏心窝的话真正的好固件不是靠神秘参数魔改出来的而是靠理解设备固件逻辑之后做精准、克制的调整。gsetupmod 这类工具的价值恰恰在于让你能自己掌控这套逻辑而不是依赖别人的成品。4.4 常见问题速查表现象可能原因解决建议修改后重启没有新菜单条件变量不止一个查询所有关联变量逐一修改变量写入了但值被强制恢复固件启动流程会重置默认值检查默认变量表存储位置改默认值修改其他选项时会闪退变量空间不足清理冗余变量后再试找不到任何隐藏选项固件已签名/加密封装确认固件是否加密可能需要先解包Secure Boot 开启时报签名错误变量修改破坏了签名链暂时关闭签名验证或恢复原变量再重新修改还有一个容易被忽略的问题部分 ARM 笔记本和超薄设备使用的主控固件不是标准 UEFI而是厂商定制的轻量级引导环境这类设备并不适用于本文介绍的流程。开始操作前先确认你的设备确实运行的是 UEFI 固件可以在启动时看有没有 UEFI Shell 入口或者查一下设备规格是否标注支持 UEFI 启动。如果是纯定制引导环境gsetupmod 帮不上忙得换另一套思路。5. 后续还能怎么玩以及几点个人体会把 ARM 平台的隐藏菜单打开之后你会发现可玩性比想象中大不少。串口调试开关、PCIe 链路策略、ACPI 日志等级、部分芯片组功耗调度选项这些都是平时很难通过操作系统层面改的一旦能在 Setup 页面直接操作调试和优化效率会高很多。特别是做嵌入式开发的朋友某些板卡的串口重定向选项隐藏得很深有了 gsetupmod 就能快速打开不用再为了一个调试口去折腾编译整套固件。我个人实际用下来的体会是gsetupmod 的 ARM 版本已经可以胜任绝大部分常见场景但毕竟项目还年轻对某些厂商的私有扩展做适配仍需时间。建议在动手之前先把当前固件完整备份一份并把原始的变量清单导出来保存这样每次修改都有据可查也方便回滚。改 BIOS 从来不是为了炫技而是在可控范围内解决实际问题。相比直接刷别人做好的定制固件自己动手定位隐藏项、修改变量、反复验证这个过程虽然慢一些但对设备逻辑的理解会深一个层次。最后提醒一点任何固件级别的修改都存在风险尤其是 ARM 平台设备很多没有双 BIOS 设计刷坏了恢复成本高。如果不是必须解锁某个隐藏项完全可以不去动它如果确实需要那就按“备份 → 查询 → 小范围修改 → 验证”的顺序来不要一上来就批量开启所有隐藏项。工具只是手段稳才是第一位。