Firmwareupdate für mobiles Breitbandgerät
Dieser Artikel enthält eine Anleitung für Hersteller von Mobile Broadband (MB)-Modulen, die Firmware-Update-Geräte über Windows Update (WU) unterstützen möchten. Die Geräte müssen mit der USB NCM Mobile Broadband Interface Model (MBIM) V1.0 Spezifikation konform sein, die von der USB-IF Device Working Group veröffentlicht wurde.
Die Informationen in diesem Artikel gelten für:
- Windows 8/Windows 10/Windows 11
Geräteanforderungen
Um Firmware-Updates auf Mobile Broadband mit Windows Update zu unterstützen, müssen die Hersteller von Modulen oder Geräten die folgenden Anforderungen erfüllen:
- Ein vom Modul- oder Gerätehersteller entwickelter Treiber auf UMDF-Basis (User-Mode Driver Framework), der zusammen mit der INF-Datei und dem Payload der Firmware gepackt ist. Ein Beispiel für eine INF-Datei und weitere Details finden Sie in einem späteren Element dieses Dokuments
- Geräte-Firmware zur Implementierung der folgenden Funktionalitäten:
- Firmware-ID-Dienst für Geräte (FID). Weitere Informationen finden Sie unter FID-Dienst für Geräte.
- Firmware zur Unterstützung eines Firmware-Update-Dienstes für Geräte. Hierbei handelt es sich um einen geräteherstellerspezifischen Dienst, der es einem UMDF-Treiber ermöglicht, den Firmware-Payload aufzurufen und auszuführen/herunterzuladen und den Firmware-Aktualisierungsprozess zu starten.
Übersicht über den Vorgang
Das folgende Diagramm zeigt das High-Level-Design und die Interaktion zwischen den drei beteiligten Komponenten: MBIM Gerät, Windows 8-Betriebssystem und der von IHV gelieferte Firmware-Upgrade-Treiber.
- Wenn der WWAN-Dienst die Ankunft eines neuen MB-Geräts erkennt, prüft er, ob das Gerät den Firmware-ID-(FID)-Device-Dienst unterstützt. Wenn dies der Fall ist, ruft er die FID ab, die als GUID definiert ist. Die Spezifikation des FID-Dienstes, die das IHV zur Unterstützung des Geräts benötigt, wird unten beschrieben.
- Der WWAN-Dienst (Windows-Betriebssystem) generiert einen „Soft-Dev-Knoten“ unter Verwendung der oben abgerufenen FID als Hardware-ID des Geräts. Dies wird im obigen Diagramm als „Soft Dev-Knoten“ bezeichnet. Die Erstellung des Dev-Knotens löst das PnP-Subsystem (Windows-Betriebssystem) aus, um den am besten passenden Treiber zu finden. In Windows 8 versucht das PnP-System zunächst, einen Treiber aus dem lokalen Store zu installieren, falls einer verfügbar ist, und parallel dazu versucht das Betriebssystem, einen besser passenden Treiber von WU abzurufen. Der Inbox-NULL-Treiber wird als Standard verwendet, wenn kein besser passender Treiber verfügbar ist, um das Problem „Treiber nicht gefunden“ zu beseitigen.
- Das IHV-WU-Paket, das auf der FID-Übereinstimmung basiert, wird auf den Computer heruntergeladen und installiert. Es wird erwartet, dass die FID eine eindeutige Firmware-SKU darstellt (Eindeutigkeit wird hier durch die Kombination Gerät VID/PID/REV und MNO definiert). Das WU-Paket würde einen von IHV erstellten UMDF-Treiber sowie einen Firmware-Payload enthalten.
- Sobald der IHV-UMDF auf den Soft-Dev-Knoten geladen ist, trägt er die Verantwortung für die Steuerung des Firmware-Update-Flows. Beachten Sie, dass die Lebensdauer des Soft-Dev-Knotens an die physische Anwesenheit des MBIM-Geräts gebunden ist. Der UMDF-Treiber führt die folgenden Schritte zur Durchführung von Firmware-Updates durch
- Es ist akzeptabel, dass das Gerät während des Firmware-Updates mehrmals neu gestartet wird, was jedoch dazu führen würde, dass der UMDF-Treiber entladen/neu geladen wird
- Der gesamte Prozess der Firmware-Aktualisierung, einschließlich der Neustarts, sollte nicht länger als 60 Sekunden dauern.
- Nachdem das Firmware-Update abgeschlossen ist und das Gerät in den MBIM-Modus zurückgekehrt ist, sollte Windows benachrichtigt werden. Dies geschieht durch Löschen der zuvor festgelegten Eigenschaft DEVPKEY_Device_PostInstallInProgress. Die IWDFUnifiedPropertyStore Schnittstelle beschreibt, wie Sie eine Eigenschaft auf dem Dev-Knoten festlegen. Eine zuvor festgelegte Eigenschaft kann mit DEVPROP_TYPE_EMPTY gelöscht werden.
- Während des OnPrepareHardware-UMDF-Callbacks prüft der UMDF-Treiber, ob die Firmware des Geräts aktualisiert werden muss. Dazu wird die Version der Firmware auf dem Gerät mit der Version verglichen, die über Windows Update eingegangen ist. Weitere Anleitungen zum Speicherort der Firmware-Binardateien finden Sie weiter unten in diesem Dokument. Wenn ein Firmware-Update erforderlich ist, sollte der UMDF-Treiber:
- Ein Work-element einplanen. Das eigentliche Upgrade der Firmware findet im Rahmen des Work-Elements statt.
- Sobald das Work-Element erfolgreich geplant wurde, benachrichtigen Sie Windows über den Start des Firmware-Updates. Dazu legen Sie die Eigenschaft DEVPKEY_Device_PostInstallInProgress auf dem Soft-Dev-Knoten im Kontext des OnPrepareHardware-UMDF-Callbacks fest.
- Es ist wichtig, dass Sie den OnPrepareHardware-Callback nicht blockieren, während das Firmware-Update läuft. Es wird erwartet, dass der OnPrepareHardware-Callback innerhalb von ein oder höchstens zwei Sekunden abgeschlossen ist.
Beispiel-INF-Datei für das WU-Paket
In diesem Abschnitt finden Sie ein Beispiel für eine INF-Datei, die Teil des WU-Pakets ist. Die wichtigsten Punkte, die Sie in der INF-Datei beachten sollten, sind:
- Die Binardateien der Firmware sind unabhängig vom UMDF-Treiber.
- Die Binardateien der Firmware befinden sich im Verzeichnis driverstore, einem vom Betriebssystem festgelegten Pfad, auf den in der INF mit DIRID 13 verwiesen wird. Bei den Binardateien kann es sich nicht um ausführbare Dateien handeln, die PE/COFF-Header enthalten.
%13%\<UniqueBinaryName>.bin
- Die INF-Datei speichert diesen Speicherort in der Registrierung und der UMDF-Treiber liest den Registrierungswert, um den Binärort zu ermitteln.
- Das folgende Beispiel einer INF-Vorlage zeigt, welche Anforderungen die IHV erfüllen muss.
[Version]
Signature = "$WINDOWS NT$"
Class = Firmware
ClassGuid = {f2e7dd72-6468-4e36-b6f1-6488f42c1b52}
Provider = %Provider%
DriverVer = 06/21/2006,6.2.8303.0
CatalogFile = MBFWDriver.cat
PnpLockdown = 1
[Manufacturer]
%Mfg% = Firmware,NTx86
[Firmware.NTx86]
%DeviceDesc% = Firmware_Install,MBFW\{FirmwareID} ; From Device Service
;%DeviceDesc% = Firmware_Install,MBFW\{2B13DD42-649C-3442-9E08-D85B26D7825C}
[Firmware_Install.NT]
CopyFiles = FirmwareDriver_CopyFiles,FirmwareImage_CopyFiles
[Firmware_Install.NT.HW]
AddReg = Device_AddReg
[Device_AddReg]
HKR,,FirmwareBinary,,"%13%\MBIHVFirmware-XYZ-1.0.bin"
[Firmware_Install.NT.Services]
AddService = WUDFRd,0x000001fa,WUDFRD_ServiceInstall
[WUDFRD_ServiceInstall]
DisplayName = %WudfRdDisplayName%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %12%\WUDFRd.sys
LoadOrderGroup = Base
[Firmware_Install.NT.CoInstallers]
CopyFiles = WudfCoInstaller_CopyFiles
[WudfCoInstaller_AddReg]
HKR,,CoInstallers32,0x00010000,"WUDFCoinstaller.dll"
[Firmware_Install.NT.Wdf]
UmdfService = MBIHVFirmwareDriver,MBIHVFirmwareDriver_Install
UmdfServiceOrder = MBIHVFirmwareDriver
[MBIHVFirmwareDriver_Install]
UmdfLibraryVersion = 1.11
ServiceBinary = %12%\UMDF\MBFWDriver.dll
DriverCLSID = {<DriverClassGuid>} ; From UMDF driver
[FirmwareImage_CopyFiles]
MBIHVFirmware-XYZ-1.0.bin ; Firmware Image
[FirmwareDriver_CopyFiles]
MBFWDriver.dll ; UMDF driver for SoftDevNode
[DestinationDirs]
FirmwareImage_CopyFiles = 13 ; Driver Store
FirmwareDriver_CopyFiles = 12,UMDF ;%SystemRoot%\System32\drivers\UMDF
[SourceDisksFiles]
MBIHVFirmware-XYZ-1.0.bin = 1
[SourceDisksNames]
1 = %DiskName%
; ================== Generic ==================================
[Strings]
Provider = "MBIHV"
Mfg = "MBIHV"
DeviceDesc = "MBIHV Mobile Broadband Firmware Device"
DiskName = "Firmware Driver Installation Media"
Firmware-Identifikationsdienst für Geräte (FID-Dienst))
Das MBIM-konforme Gerät implementiert den folgenden Dienst und liefert ihn, wenn er von CID_MBIM_DEVICE_SERVICES abgefragt wird. Die bestehenden bekannten Dienste sind in der NCM MBIM-Spezifikation in Abschnitt 10.1 definiert. Die Microsoft Corporation erweitert diese und definiert den folgenden Dienst.
Dienstname = Microsoft Firmware ID
UUID = UUID_MSFWID UUID
Value = e9f7dea2-feaf-4009-93ce-90a3694103b6
Konkret ist für den Gerätedienst UUID_MSFWID die folgende CID definiert:
CID = CID_MBIM_MSFWID_FIRMWAREID
Befehlscode = 1
Query = Yes
Set = No
Event = No
Set InformationBuffer payload = N/A
Query InformationBuffer payload = N/A
Completion InformationBuffer payload = UUID
CID_MBIM_MSFWID_FIRMWAREID
Der Befehl gibt die von MNO oder IHV zugewiesene Firmware-ID für das Gerät zurück. Die UUID wird auf der Grundlage der Richtlinien in der MBIM-Spezifikation kodiert.
Query = InformationBuffer on MBIM_COMMAND_MSG not used. UUID returned in InformationBuffer MBIM_COMMAND_DONE.
Set = Unsupported
Unsolicited Event = Unsupported
Code-Schnipsel für das Verhalten des UMDF-Treibers
Wie bereits angedeutet, sollte der UMDF-Treiber Windows mitteilen, wann er das Firmware-Upgrade startet und abschließt. Dieser Abschnitt enthält Code-Schnipsel, die zeigen, wie der Treiber Windows über diese Ereignisse informieren sollte.
/**
* This is the IPnpCallbackHardware*:OnPrepareHardware handler
* in the UMDF driver. This is called every time the firmware
* update is device is started. Since this handler should be
* blocked from returning actual the firmware update process
* should be done in a workitem
*/
HRESULT
CMyDevice::OnPrepareHardware(IWDFDevice* pDevice)
{
HRESULT hr = S_OK;
BOOL bFirmwareUpdateInProgress = FALSE;
BOOL bFirmwareUpdateNeeded = FALSE;
BOOL bFirmwareUpdateIsDone = FALSE;
//
// The snippets below demonstrates the steps for firmware
// update against a MB device that loads the updated firmware
// on device boot. So the firmware update driver needs to
// send the new firmware down to the device and then tell
// the device to initiate a stop/start. Once the device has
// reappeared, it would have automatically loaded the
// new firmware
//
//
// First, determine if firmware update is in progress. This
// can be based on some registry key that is saved when
// firmware update is started
//
// Assuming this status is returned in bFirmwareUpdateInProgress
if (bFirmwareUpdateInProgress)
{
//
// If firmware update is in progress, check if its done. For
// this it may be necessary to access the MB device. Note that
// if the MB device (& hence the Firmware update device) needs
// multiple stop/starts to do the firmware update. In that case
// it will be marked as done at the end of the process
//
// Assuming this status is returned in bFirmwareUpdateIsDone
if (bFirmwareUpdateIsDone)
{
//
// Signal the completion of the firmware update
// process.
//
SignalFirmwareUpdateComplete(pDevice);
}
else
{
//
// Take appropriate steps to get notified when
// firmware update is done. Call SignalFirmwareUpdateComplete
// when that notification is received
//
}
}
else
{
//
// Determine if firmware update is needed. This can be
// based on checking state in the registry of the last
// firmware version set on the device to the firmware
// version associated with this driver
//
// Assuming this status is returned in bFirmwareUpdateNeeded
if (bFirmwareUpdateNeeded)
{
//
// Create and queue a workitem to perform the firmware
// update process. IWDFWorkItem can be used for this
//
// Assuming the creation/enquing status
// is returned in hr
if (SUCCEEDED(hr))
{
//
// Work item queued. It will do the firmware update
// Tell the OS that firmware update is in progress
//
SignalFirmwareUpdateInProgress(pDevice);
}
}
}
//
// If we have a failure, we clear the firmware update
// in progress state
//
if (FAILED(hr))
{
SignalFirmwareUpdateComplete(pDevice);
}
return S_OK;
}
/**
* This function tells the OS that firmware update is in progress.
* It should be called from the firmware update UMDF driver's
* IPnpCallbackHardware*:OnPrepareHardware handler after it has
* successfully queued a workitem to perform the firmware update
*/
HRESULT
CMyDevice::SignalFirmwareUpdateInProgress(
__in IWDFDevice* pDevice
)
{
HRESULT hr = S_OK;
IWDFUnifiedPropertyStoreFactory* spPropertyStoreFactory = NULL;
IWDFUnifiedPropertyStore* spPropStore = NULL;
WDF_PROPERTY_STORE_ROOT wdfPropRoot = { sizeof(WDF_PROPERTY_STORE_ROOT), WdfPropertyStoreRootClassHardwareKey };
DEVPROP_BOOLEAN boolValue = DEVPROP_TRUE;
do
{
hr = pDevice->QueryInterface(IID_PPV_ARGS(&spPropertyStoreFactory));
if (FAILED(hr))
{
Trace(TRACE_LEVEL_ERROR, "Failed to query for property store factory. Error = 0x%x", hr);
break;
}
hr = spPropertyStoreFactory->RetrieveUnifiedDevicePropertyStore(
&wdfPropRoot,
&spPropStore
);
if (FAILED(hr))
{
Trace(TRACE_LEVEL_ERROR, "Failed to query for device property store. Error = 0x%x", hr);
break;
}
// Set the OS flag
hr = spPropStore->SetPropertyData(
reinterpret_cast<const DEVPROPKEY*>(&DEVPKEY_Device_PostInstallInProgress),
0, // this property is language neutral
0,
DEVPROP_TYPE_BOOLEAN,
sizeof(DEVPROP_BOOLEAN),
&boolValue
);
if (FAILED(hr))
{
Trace(TRACE_LEVEL_ERROR, "Failed to set device property for PostInstallInProgress. Error = 0x%x", hr);
break;
}
//
// Save some state so that we know we are in the process
// of firmware update
//
} while (FALSE);
if (spPropStore)
{
spPropStore->Release();
}
if (spPropertyStoreFactory)
{
spPropertyStoreFactory->Release();
}
return hr;
}
/**
* This function tells the OS that firmware update is done
* It should be called only after the full firmware update process
* (including any MB device stop/start) has finished
*/
HRESULT
CMyDevice::SignalFirmwareUpdateComplete(
__in IWDFDevice* pDevice
)
{
HRESULT hr = S_OK;
IWDFUnifiedPropertyStoreFactory* spPropertyStoreFactory = NULL;
IWDFUnifiedPropertyStore* spPropStore = NULL;
WDF_PROPERTY_STORE_ROOT wdfPropRoot = { sizeof(WDF_PROPERTY_STORE_ROOT), WdfPropertyStoreRootClassHardwareKey };
do
{
hr = pDevice->QueryInterface(IID_PPV_ARGS(&spPropertyStoreFactory));
if (FAILED(hr))
{
Trace(TRACE_LEVEL_ERROR, "Failed to query for property store factory. Error = 0x%x", hr);
break;
}
hr = spPropertyStoreFactory->RetrieveUnifiedDevicePropertyStore(
&wdfPropRoot,
&spPropStore
);
if (FAILED(hr))
{
Trace(TRACE_LEVEL_ERROR, "Failed to query for device property store. Error = 0x%x", hr);
break;
}
hr = spPropStore->SetPropertyData(
reinterpret_cast<const DEVPROPKEY*>(&DEVPKEY_Device_PostInstallInProgress),
0, // this property is language neutral
0,
DEVPROP_TYPE_BOOLEAN,
0,
NULL
);
if (FAILED(hr))
{
Trace(TRACE_LEVEL_ERROR, "Failed to clear device property for PostInstallInProgress. Error = 0x%x", hr);
break;
}
//
// Save some state so that we can do quick check on
// whether firmware update is needed or not
//
} while (FALSE);
if (spPropStore)
{
spPropStore->Release();
}
if (spPropertyStoreFactory)
{
spPropertyStoreFactory->Release();
}
return hr;
}