使用 Windows 更新 更新设备固件

本文介绍如何使用 Windows 更新 (WU) 服务更新可移动或机箱内设备的固件。 有关更新系统固件的信息,请参阅 Windows UEFI 固件更新平台

为此,你将提供包含固件有效负载的设备驱动程序。 如果为设备提供函数驱动程序,则可以将固件更新逻辑和有效负载添加到现有驱动程序,也可以提供单独的固件更新驱动程序包。 如果设备使用Microsoft提供的驱动程序,则必须提供单独的固件更新驱动程序包。 在这两种情况下,固件更新驱动程序包必须是通用的。

有关通用驱动程序的详细信息,请参阅 使用通用 INF 文件。 驱动程序二进制文件可以使用 KMDFUMDF 2Windows 驱动程序模型

由于 WU 无法执行软件,因此固件更新驱动程序必须将固件交给 即插即用 (PnP) 进行安装。

固件更新驱动程序操作

通常,固件更新驱动程序是实现以下过程的轻型设备驱动程序:

  • 在设备启动时或驱动程序的 EVT_WDF_DRIVER_DEVICE_ADD 回调函数中:

    1. 标识其附加到的设备。

    2. 确定驱动程序的固件版本是否比设备硬件上当前闪烁的固件版本更新。

    3. 如果需要固件更新,请设置事件计时器以计划更新。

    4. 否则,在再次启动驱动程序之前,不执行任何操作。

  • 在系统运行时:

    1. 如果更新已排队,请等待满足一组条件。

    2. 满足条件时,请在设备上执行固件更新。

固件更新驱动程序内容

通常,固件更新驱动程序包包含以下项:

  • 通用驱动程序 INF

  • 驱动程序目录

  • 函数驱动程序(.sys或.dll)

  • 固件更新有效负载二进制文件

将固件更新包作为单独的驱动程序提交提交。

将固件更新逻辑添加到供应商提供的驱动程序

现有函数驱动程序可以实现固件更新机制,如下图所示:

使用Windows 更新通过现有函数驱动程序传送固件更新。

或者,如果要单独更新函数驱动程序和固件更新驱动程序,请创建另一个设备节点,在该节点上安装固件更新驱动程序。 下图显示了一个设备如何具有两个单独的设备节点:

使用Windows 更新通过单独的设备节点传送固件更新。

在这种情况下,函数和固件设备节点必须具有不同的硬件 ID 才能独立定位。

可通过多种方式创建第二个设备节点。 某些设备类型能够在一个物理设备(如 USB)上公开第二个设备节点。 可以使用此功能创建可由 WU 定向的设备节点,并在其上安装固件更新驱动程序。 但是,许多设备类型不允许单个物理设备枚举多个设备节点。

在这种情况下,请使用指定 AddComponent 指令的扩展 INF 来创建设备节点,该节点可由Windows 更新并安装固件更新驱动程序。 INF 文件中的以下代码片段演示如何执行此操作:

[Manufacturer]
%Contoso%=Standard,NTamd64
[Standard.NTamd64]
%DeviceName%=Device_Install, PCI\DEVICE_ID
[Device_Install.Components]
AddComponent=ComponentName,,AddComponentSection
[AddComponentSection]
ComponentIDs = ComponentDeviceId

在上面的 INF 示例中,ComponentIDs = ComponentDeviceId指示子设备将具有硬件 ID。SWC\ComponentDeviceId 安装后,此 INF 将创建以下设备层次结构:

父设备、主设备、AddComponent 设备。

对于将来的固件更新,请更新包含固件有效负载的 INF 和二进制文件。

将固件更新逻辑添加到Microsoft提供的驱动程序

若要为使用Microsoft提供的驱动程序的设备更新固件,需要创建第二个设备节点,如下所示。

最佳做法

  • 在固件更新驱动程序 INF 中,指定 DIRID 13 会导致 PnP 在 DriverStore 的驱动程序包中保留文件:

    [Firmware_AddReg]
    ; Store location of firmware payload
    HKR,,FirmwareFilename,,"%13%\firmware_payload.bin"
    

    PnP 在安装设备时解析此位置。 然后,驱动程序可以打开此注册表项以确定有效负载的位置。

  • 固件更新驱动程序应指定以下 INF 条目:

    Class=Firmware
    ClassGuid={f2e7dd72-6468-4e36-b6f1-6488f42c1b52}
    
  • 若要查找另一个设备节点,固件驱动程序应通过枚举匹配的所有设备节点来相对于自身走设备树。 用户可能已插入设备的多个实例,固件驱动程序应仅更新与其关联的设备。 通常,要定位的设备节点是安装固件驱动程序的设备节点的父级或同级节点。 例如,在上图中,有两个设备节点,固件更新驱动程序可以查找同级设备来查找函数驱动程序。 在上图中,固件驱动程序可以查找父设备以查找需要与其通信的主要设备。

  • 驱动程序应对系统上的多个设备实例(可能具有多个不同固件版本)可靠。 例如,可能有一个设备实例已连接并多次更新;然后,可以插入一个全新的设备,其中几个固件版本旧。 这意味着(例如当前版本)必须针对设备存储状态,而不是存储在全局位置。

  • 例如,如果有更新固件的现有方法(例如 EXE 或共同安装程序),则基本上可以在 UMDF 驱动程序中重复使用更新代码。