创作更新驱动程序包

需要将 ESRT 中所述的每个固件资源的更新有效负载捆绑在一起,并在各自的驱动程序包中分发,以便它能够维护自己的版本控制方案,而无需绑定到可能不以同一节奏更新的其他固件资源更新。

以下示例为面向表 2 中 ESRT 示例的 {SYSTEM_FIRMWARE} 资源的固件资源更新提供了示例驱动程序包 INF 文件定义,并将它从版本 1 更新到版本 2。 出于参考目的,假设为bbSYSTEM_FIRMWAREb资源分配的 GUID 为 6bd4efb9-23cc-4b4a-ac37-016517413e9a。

[Version]
Signature   = "$WINDOWS NT$"
Provider    = %Provider%
Class       = Firmware
ClassGuid   = {f2e7dd72-6468-4e36-b6f1-6488f42c1b52}
DriverVer   = 01/01/2012,2.0.0.0
CatalogFile = catalog.cat
PnpLockdown = 1

[Manufacturer]
%MfgName% = Firmware,NTarm64.10.0...17134
; Prior to Windows 10, version 1803, the above should instead be:
; %MfgName% = Firmware,NTarm64

[Firmware.NTarm64.10.0...17134]
; Prior to Windows 10, version 1803, the above should instead be:
; [Firmware.NTarm64]
%FirmwareDesc% = Firmware_Install,UEFI\RES_{6bd4efb9-23cc-4b4a-ac37-016517413e9a}

[Firmware_Install.NT]
CopyFiles = Firmware_CopyFiles

[Firmware_CopyFiles]
firmware.bin

[Firmware_Install.NT.Hw]
AddReg = Firmware_AddReg

[Firmware_AddReg]
HKR,,FirmwareId,,{6bd4efb9-23cc-4b4a-ac37-016517413e9a}
HKR,,FirmwareVersion,%REG_DWORD%,0x00000002
HKR,,FirmwareFilename,,%13%\firmware.bin
; Prior to Windows 10, version 1803, the above should instead be:
; HKR,,FirmwareFilename,,{6bd4efb9-23cc-4b4a-ac37-016517413e9a}\firmware.bin

[SourceDisksNames]
1 = %DiskName%

[SourceDisksFiles]
firmware.bin = 1

[DestinationDirs]
DefaultDestDir = 13
; Prior to Windows 10, version 1803, the above should be:
; DefaultDestDir = 10,Firmware\{6bd4efb9-23cc-4b4a-ac37-016517413e9a}

[Strings]
; localizable
Provider     = "Contoso Ltd."
MfgName      = "Fabrikam Inc."
FirmwareDesc = "Fabrikam System Firmware 2.0"
DiskName     = "Firmware Update"

; non-localizable
REG_DWORD     = 0x00010001

更改以下部分以针对设置进行自定义。

[Version]
DriverVer --> The date on which this driver package was authored and the driver version of this driver package. Driver version in this driver package must be greater than the current driver version
CatalogFile --> Name of the catalog file

firmware.bin --> Change all instances of firmware.bin with the name of the firmware image name

[Manufacturer]
%MfgName% = Firmware,NTarm64.10.0...17134
[Firmware.NTarm64.10.0...17134] --> Change the architecture.
For x86, it should be NTx86
For AMD64, it should be NTamd64

[Firmware.NTarm64.10.0...17134]
%FirmwareDesc% = Firmware_Install,UEFI\RES_{6bd4efb9-23cc-4b4a-ac37-016517413e9a} --> The GUID of the firmware resource

[Firmware_AddReg]
HKR,,FirmwareId,,{6bd4efb9-23cc-4b4a-ac37-016517413e9a} --> The GUID of the firmware resource
HKR,,FirmwareVersion,%REG_DWORD%,0x00000002 --> Version of the firmware for the update
HKR,,FirmwareFilename,,%13%\firmware.bin --> firmware.bin should be replaced with the firmware image name
; Prior to Windows 10, version 1803, the above should instead be:
HKR,,FirmwareFilename,,{6bd4efb9-23cc-4b4a-ac37-016517413e9a}\firmware.bin --> The subdirectory named after the GUID of the firmware resource and the firmware image name

[DestinationDirs]
DefaultDestDir = 13 --> The full destination path as a 'run from Driver Store' binary
; Prior to Windows 10, version 1803, the above should be:
; DefaultDestDir = 10,Firmware\{6bd4efb9-23cc-4b4a-ac37-016517413e9a} --> The full destination path for the firmware image file based under a subdirectory named after the GUID of the firmware resource within the %SystemRoot%\Firmware directory

[Strings]
; localizable
Modify any strings here [optional]

下表介绍了引用上述示例驱动程序包 INF 文件定义的各种驱动程序包 INF 节和字段。

节/字段 注释
[Version] 定义驱动程序包版本控制信息。
提供程序 %Provider% = Contoso Inc.

(本地化为 [Strings] 节)
标识整个固件资源更新驱动程序包的提供商/供应商。
Class/ClassGuid 固件/

{f2e7dd72-6468-4e36-b6f1-6488f42c1b52}
指定驱动程序包的日期。 日期和时间应同时最贴切地反映实际固件资源更新的日期和时间,以确保 PnP 设备安装系统能够准确选择系统上可用的最佳驱动程序包。
CatalogFile catalog.cat 指定对驱动程序包 INF 文件和所有关联的固件资源更新二进制文件进行签名的关联目录文件。
PnpLockdown 1 启用 PnP 驱动程序文件锁定机制,以保护已安装的驱动程序文件不受不相关应用程序外部修改。 对于固件资源更新,应始终启用此设置,以确保固件资源映像文件不能在 PnP 系统的控制范围之外被篡改
[Manufacturer] 列出定义固件资源更新的所有不同驱动程序制造商/供应商。 每个制造商行指定一个 [<Models>] 节,并标识其支持的目标平台。
%MqName% Fabrikam Inc.

(本地化为 [Strings] 节)
标识固件资源更新的制造商/供应商。 这可能与“提供商”字段相同。
固件,

NTarm64.10.0...17134
标识用于定义此驱动程序包支持的固件资源设备的 [<Models>] 节,包括其目标驱动程序平台。 在此示例中,驱动程序仅面向基于 Arm64 的 NT 平台(适用于 Windows 10 内部版本 17134 及更高版本),[<Models>] 节为 [Firmware.NTarm64.10.0...17134]。
[Firmware.NTarm64.10.0...17134] [<Models>] 节,对应适用于 Windows 10 内部版本 17134 及更高版本的基于 Arm64 的 NT 平台,其中列出了定义更新的所有固件资源设备。 每个硬件模型行指定 [<DDInstall>] 节及其关联的硬件 ID 匹配。
%FirmwareDesc% Fabrikam 系统固件 2.0

(本地化为 [Strings] 节)
描述固件资源更新。 这是用于在设备管理器和其他与设备相关的 UI 中显示关联的固件资源设备实例的主要说明字符串。 因此,说明可能包含固件供应商和版本。
Firmware_Install,

UEFI\RES_{RESOURCE_GUID}
标识 [<DDInstall] 节,其中包含固件资源更新的安装步骤,该更新面向由 UEFI\RES_{RESOURCE_GUID} 硬件 ID 标识的设备实例。 其中,RESOURCE_GUID 是正在更新的固件资源的 GUID。
[Firmware_Install.NT]

CopyFiles = Firmware_CopyFiles

[Firmware_CopyFiles]

...
[<DDInstall>] 节,其中包含固件资源更新的安装步骤。 对于固件资源更新,这只会定义固件资源映像文件以就地复制固件资源更新。 在此示例中,[<DDInstall>] 节为 [Firmware_Install.NT]。
firmware.bin 指定要复制的固件资源更新映像文件。 有关此文件复制位置的详细信息,请参阅下面的 [DestinationDirs] 节。
[Firmware_Install.NT.Hw]

AddReg = Firmware_AddReg

[Firmware_AddReg]

...
[<DDInstall>.Hw] 节,其中包含固件资源更新的硬件特定安装步骤。 对于固件资源更新,这会以在目标设备实例的设备硬件密钥下设置的注册表值的形式定义固件资源更新配置信息。
FirmwareId {RESOURCE_GUID} 固件资源更新的固件 GUID。 请注意,这是嵌入在 UEFI\RES_{RESOURCE_GUID} 硬件 ID 中的固件资源 GUID,但必须将其指定为独立值,因为 PnP 系统会将所有硬件 ID 视为严格用于设备/驱动程序匹配目的的不透明字符串。
FirmwareVersion 0x00000002 固件资源更新的固件版本,指定为 REG_DWORD 值。
FirmwareFilename %13%\firmware.bin 在 Windows 10 版本 1803 及更高版本上,这应该是 'run from Driver Store' 文件,并提供二进制文件的完整路径,如示例中所示。 对于 Windows 10 版本 1803 之前的版本,这应该是固件资源更新的 Update Capsule 映像文件名在 %SystemRoot%\Firmware 目录下的相对路径和固件文件名,以便 {RESOURCE_GUID} 表示用于整理针对特定固件资源的所有固件映像文件的子目录。 例如,{RESOURCE_GUID}\firmware.bin
[SourceDisksNames] 列出包含关联的驱动程序文件(如固件更新资源映像文件)的所有不同驱动程序包源磁盘位置。
1 %DiskName% = 固件更新

(本地化为 [Strings] 节)
指定任意编号的驱动程序包源磁盘 ID 及其说明名称。 未指定可选驱动程序包相对子目录,因此与此磁盘 ID 关联的任何驱动程序文件(如固件资源更新映像文件)应直接位于 INF 文件旁边。
[SourceDisksFiles] 列出驱动程序包引用的所有驱动程序文件,并将其链接到 [SourceDisksNames] 节中的磁盘 ID。
firmware.bin 1 通过将 firmware.bin 固件资源更新映像文件链接到主磁盘 ID,将其作为驱动程序包的一部分建立。 未指定任何特定于文件的可选子目录,因此此驱动程序文件应相对于其磁盘 ID 的子目录放置,在本例中位于 INF 文件旁边。
[DestinationDirs] 列出驱动程序包所引用的所有驱动程序文件的目标目的地目录。
DefaultDestDir 13 指定此驱动程序包复制的所有驱动程序文件的默认目标目录。 在 Windows 10 版本 1803 及更高版本上,这应该是 DIRID 13,以使文件”从驱动程序存储运行“。 在 Windows 10 版本 1803 之前,这应为 10,Firmware\{RESOURCE_GUID} 以指定所有文件的目的地位于 %SystemRoot%\Firmware 下,其中 10 (DIRID_WINDOWS) 表示基本 %SystemRoot% 目录,{RESOURCE_GUID} 表示以固件资源 GUID 命名的子目录。
[Strings] 定义驱动程序包 INF 文件中所有间接字符串令牌 (%token%) 的键/值映射。 使用字符串令牌,可以通过引入特定于区域设置的 [Strings.<LanguageID>] 节轻松本地化驱动程序包 INF 文件。 还可以使用字符串令牌替换来定义常量数值,例如 REG_DWORD。
提供程序 "Contoso Ltd." 字符串令牌键/值映射的示例。

请务必为每个固件资源更新映像文件版本使用唯一名称,以避免与其他固件映像文件(你自己的和来自其他固件供应商的固件映像文件)发生任何潜在冲突。 例如,应为上文中的 firmware.bin 分配以下名称以满足供应商名称和版本约束:Fabrikam-System-Firmware-2.0.bin

为了确保给定固件资源更新映像的变体(可能用于 OEM/IHV 定制目的)在部署到同一 Windows 系统映像时不会发生冲突,建议每个不同的固件资源更新映像是 'run from Driver Store' 文件(Windows 10 版本 1803 及更高版本)或在 %SystemRoot%\Firmware 目录中的子目录下维护。 此子目录应以目标固件资源 GUID 命名。 例如,以下固件资源更新映像路径满足部署约束:%SystemRoot%\\Firmware\\{6bd4efb9-23cc-4b4a-ac37-016517413e9a}\\Fabrikam-System-Firmware-2.0.bin

测试对固件驱动程序包进行签名

驱动程序包 INF 文件和固件有效负载二进制文件准备就绪后,必须对整个驱动程序包进行签名才能生成目录文件。 此目录文件必须保证驱动程序包中包含的 INF 文件和固件有效负载二进制文件的有效性和真实性,以使 Windows 能够安全地启动固件资源更新。

下面枚举了用于测试目的自签名驱动程序包的步骤。 请注意,这些步骤仅用于测试目的。 在生产环境中,固件更新驱动程序包必须提交到合作伙伴中心进行签名。 有关为生产环境对固件驱动程序包进行签名的步骤,请参阅认证和签名更新包

  1. 安装最新的 Windows SDK 和 Windows 驱动程序工具包。 这将在 %systemdir%\Program Files (x86)\Windows Kits\<*version*>\bin\x86 下安装 makecert、pvk2pfx inf2cat 和 signtool 工具。

  2. 运行以下命令以创建测试证书。

    makecert.exe -r -pe -a sha256 -eku 1.3.6.1.5.5.7.3.3 -n CN=Foo -sv fwu.pvk fwu.cer
    pvk2pfx.exe -pvk fwu.pvk -spc fwu.cer -pi <Password entered during makecert prompt> -spc fwu.cer -pfx fwu.pfx
    

    有关详细信息,请参阅 MakeCert

  3. 运行以下命令以创建目录文件。

    Inf2Cat.exe /driver:"." /os:8_x64
    

    /driver 参数指向 INF 所在的位置。 根据固件驱动程序包面向的 OS 更改 /os 参数的值。 有关详细信息,请参阅 Inf2Cat

    有关安全目录和驱动程序的详细信息,请参阅目录文件和数字签名以及为 PnP 驱动程序包创建目录文件

  4. 运行以下命令以为目录文件签名。

    signtool sign /fd sha256 /f fwu.pfx /p <Password entered during makecert prompt> delta.cat
    

    有关详细信息,请参阅 SignTool

  5. 在测试系统上安装测试证书:

    1. 双击 fwu.cer文件,然后选择“安装证书”选项。

    2. 在证书安装过程中选择以下选项:

      • 对于“存储位置”,请选择“本地计算机”

      • 对于“证书存储”,请浏览并选择“受信任的根证书颁发机构”。

  6. 在固件/BIOS 选项中禁用安全启动。

  7. 启用 BCD 选项中的测试签名,以便 OS 加载程序可以在启动期间加载固件映像文件 (firmware.bin),即使目录未进行生产签名。 使用管理员特权运行以下命令:

    bcdedit /set testsigning on
    

在驱动程序包签名后,可以使用以下机制之一安装该包:

  • 设备管理器。 对于手动测试,设备管理器提供了一个友好的界面,用于查找固件资源设备和更新其驱动程序,以便启动固件资源更新。

    1. 在按类型查看设备时,在“固件”类下找到所需的固件资源设备,或者在按连接查看设备时在“Microsoft UEFI 兼容系统”设备下找到所需的固件资源设备。

    2. 右键单击固件资源设备,然后选择“更新驱动程序软件...”选项。

    3. 使用“浏览我的计算机以查找驱动程序软件”选项,在固件资源设备上查找并安装更新的固件资源更新驱动程序包。 此操作将确保指定的固件资源更新驱动程序包实际上比任何现有的固件资源更新驱动程序包(这些程序包可能已存在于固件资源设备上)都新,然后再将其添加到 Windows 驱动程序应用存储并启动安装。

  • pnputil。 对于自动测试,可以在管理员提升的命令提示符下使用 PnpUtil 命令行实用工具将固件资源更新驱动程序包导入 Windows 驱动程序存储中,并在当前使用较旧固件资源版本的任意/所有适用的固件资源设备上启动设备安装(由当前安装的驱动程序包 INF 文件的 DriverVer 建立,或者根本没有第三方提供的驱动程序包 INF 文件)。 例如,使用以下命令行添加并安装 X:\firmware.inf:

    pnputil -i -a X:\firmware.inf
    

如果固件资源更新已成功安装在固件资源设备上,并且它提供高于当前固件版本的固件资源更新,则设备将等待系统重启才能完成更新操作。 处于此状态的设备将通过维护设备问题来指示系统需要重新启动,从而防止设备启动并还原到稳定状态,直到执行重新启动。

验证固件更新的状态

成功安装固件驱动程序包后,PnP 将请求系统重新启动以应用更新。 重新启动后,可以验证更新的状态。 更新的状态在以下注册表项下进行维护:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FirmwareResources\{RESOURCE_GUID}

RESOURCE_GUID 是已更新的资源(来自 ESRT)的 GUID。

“LastAttemptStatus”注册表值指示固件更新的状态,其中值 0 表示成功,任何非零值表示失败。 此注册表项的值是根据 ESRT 中 LastAttemptStatus 的值由 OS 加载程序填充的 NTSTATUS 代码。 下表将 LastAttemptStatus 代码映射到相应的 NTSTATUS 代码。

LastAttemptStatus 代码 NTSTATUS 代码
Success 0 STATUS_SUCCESS 0x00000000
错误:失败 1 STATUS_UNSUCCESSFUL 0xC0000001
错误:资源不足 2 STATUS_INSUFFICIENT_RESOURCES 0xC000009A
错误:版本不正确 3 STATUS_REVISION_MISMATCH 0xC0000059
错误:图像格式无效 4 STATUS_INVALID_IMAGE_FORMAT 0xC000007B
错误:身份验证错误 5 STATUS_ACCESS_DENIED 0xC0000022
错误:电源事件,AC 未连接 6 STATUS_POWER_STATE_INVALID 0xC00002D3
错误:电源事件,电池电量不足 7 STATUS_INSUFFICIENT_POWER 0xC00002DE

固件资源设备节点的硬件 ID 属性还应反映固件版本的变化,其中 XXX 是新的固件版本。

  • UEFI\RES_{RESOURCE_GUID}&REV_XXX

如果固件更新失败,可以重试失败的固件更新:

  • 在设备管理器中,展开固件节点,右键单击固件资源设备,然后单击“更新驱动程序软件”

  • 单击“浏览计算机以获取驱动程序软件”,在下一页上,单击“从计算机的设备驱动程序列表中选择”

  • 选择之前安装的同一驱动程序,然后单击“确定”。

下次重新启动后,OS 加载程序将使用固件驱动程序包的有效负载调用 UpdateCapsule()。

ESRT 表定义

即插即用设备

处理更新

来自 UEFI 环境的设备 I/O

无缝危机预防和恢复

固件更新状态