Atualização de firmware do dispositivo de banda larga móvel
Este artigo fornece diretrizes para fabricantes de módulos de Banda larga móvel (MB) que pretendem dar suporte a dispositivos de atualização de firmware por meio do Windows Update (WU). Os dispositivos devem estar em conformidade com a Especificação USB NCM Modelo de Interface de Banda Larga Móvel (MBIM) V1.0 lançado pelo Grupo de Trabalho de Dispositivos USB-IF.
As informações neste artigo se aplicam a:
- Windows 8/Windows 10/Windows 11
Requisitos do dispositivo
Para dar suporte a atualizações de firmware na Banda Larga Móvel usando o Windows Update, os fabricantes de módulos ou dispositivos precisam estar em conformidade com os seguintes requisitos:
- Driver baseado em UMDF (User Mode Driver Framework) desenvolvido pelo fabricante do módulo ou dispositivo, empacotado junto com o arquivo INF e o conteúdo do firmware. O arquivo INF de amostra e os detalhes são fornecidos na parte posterior deste documento
- Firmware do dispositivo para implementar as seguintes funcionalidades:
- Serviço de dispositivo de ID de firmware (FID). Para obter mais informações, consulte Serviço de dispositivo FID.
- Firmware para dar suporte a um serviço de dispositivo de atualização de firmware. Esse é um serviço de dispositivo específico do fabricante do dispositivo que habilita que um driver UMDF chame e execute/baixe o conteúdo do firmware e inicie o processo de atualização do firmware.
Visão geral operacional
O diagrama a seguir mostra o design de alto nível e a interação entre os três componentes envolvidos: dispositivo MBIM, sistema operacional Windows 8 e driver de atualização de firmware fornecido pelo IHV.
- Quando o Serviço WWAN detecta a chegada de um novo dispositivo MB, ele verifica se o dispositivo suporta o Serviço de Dispositivo de ID de Firmware (FID). Se estiver presente, ele recuperará o FID, que é definido como GUID. A especificação do Serviço de Dispositivo de Firmware que o IHV precisa para o suporte no dispositivo é descrita abaixo.
- O Serviço WWAN (sistema operacional Windows) gera "nó de dispositivo flexível" usando o FID obtido acima como a ID de hardware do dispositivo. Isso é conhecido como "Nó de Desenvolvimento Flexível" no diagrama acima. A criação do nó de desenvolvimento iniciará o subsistema PnP (sistema operacional Windows) para encontrar o driver mais adequado. No Windows 8, o sistema PnP primeiro tentará instalar um driver do repositório local, se houver um disponível, e no sistema operacional paralelo tentará buscar um driver mais adequado do WU. O driver NULL da caixa de entrada será usado como padrão se o driver de melhor correspondência não estiver disponível para eliminar o problema "Driver não encontrado".
- O pacote IHV WU, com base na correspondência FID, é extraído para o computador e instalado. Espera-se que o FID represente um SKU de firmware exclusivo (a exclusividade aqui é definida pela combinação de dispositivo VID/PID/REV e MNO). O pacote WU conteria um driver UMDF criado por IHV, bem como uma carga de firmware.
- Depois que o UMDF do IHV é carregado no nó de desenvolvimento flexível, ele é responsável por controlar o fluxo de atualização do firmware. Deve-se notar que o tempo de vida do nó de desenvolvimento flexível está vinculado à presença física do dispositivo MBIM. O driver UMDF deve executar as seguintes etapas para executar atualizações de firmware
- É aceitável que o dispositivo seja reinicializado várias vezes durante o processo de atualização do firmware, mas faria com que o driver UMDF fosse descarregado/recarregado
- Todo o processo de atualização do firmware, incluindo reinicializações, não deve levar mais de que 60 segundos.
- Depois que a atualização do firmware for concluída e o dispositivo for revertido para o modo MBIM, o Windows deverá ser notificado. Isso é feito limpando a propriedade DEVPKEY_Device_PostInstallInProgress definida anteriormente. A interface IWDFUnifiedPropertyStore descreve como definir uma propriedade no nó de desenvolvimento. Uma propriedade definida anteriormente pode ser limpa usando DEVPROP_TYPE_EMPTY.
- Durante o retorno de chamada UMDF OnPrepareHardware, o driver UMDF deve verificar se o firmware no dispositivo precisa ser atualizado. Isso é feito comparando a versão do firmware no dispositivo com a que veio por meio do Windows Update. Orientações adicionais são fornecidas posteriormente no documento sobre o local de posicionamento do binário de firmware. Se a atualização do firmware for necessária, o driver UMDF deverá:
- Agende um item de trabalho. A atualização real do firmware ocorre no contexto do item de trabalho.
- Depois que o item de trabalho for agendado com êxito, notifique o Windows sobre o início da atualização do firmware. Isso é feito definindo a propriedade DEVPKEY_Device_PostInstallInProgress no nó de desenvolvimento flexível no contexto do retorno de chamada UMDF OnPrepareHardware.
- É importante não bloquear o retorno de chamada OnPrepareHardware enquanto a atualização do firmware estiver em andamento. Espera-se que o retorno de chamada OnPrepareHardware seja concluído em um ou dois segundos, no máximo.
Arquivo INF de exemplo para o pacote WU
Esta seção fornece um INF de exemplo que faz parte do pacote WU. Os principais pontos a serem observados no arquivo INF são:
- Os binários de firmware são independentes do driver UMDF.
- Os binários de firmware estão localizados no diretório driverstore, um caminho determinado pelo sistema operacional e referenciado no INF usando DIRID 13. Os binários não podem ser arquivos executáveis contendo cabeçalhos PE/COFF.
%13%\<UniqueBinaryName>.bin
- O arquivo INF armazena esse local no registro e o driver UMDF lê o valor do registro para descobrir o local binário.
- O modelo INF de exemplo a seguir destaca os itens que precisam ser preenchidos pelo IHV.
[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"
Serviço de Dispositivo de Identificação de Firmware (Serviço de Dispositivo FID)
O dispositivo compatível com MBIM implementará e relatará o seguinte serviço de dispositivo quando consultado por CID_MBIM_DEVICE_SERVICES. Os serviços conhecidos existentes são definidos na especificação MBIM do NCM na seção 10.1. A Microsoft Corporation estende isso para definir o serviço a seguir.
Nome do serviço = ID de firmware da Microsoft
UUID = UUID_MSFWID UUID
Valor = e9f7dea2-feaf-4009-93ce-90a3694103b6
Especificamente, o seguinte CID é definido para o serviço de dispositivo UUID_MSFWID:
CID = CID_MBIM_MSFWID_FIRMWAREID
Código de comando = 1
Consulta = Sim
Conjunto = Não
Evento = Não
Definir carga do InformationBuffer = N/D
Carga da consulta QueryInformationBuffer = N/D
Conclusão da carga InformationBuffer = UUID
CID_MBIM_MSFWID_FIRMWAREID
O comando retorna a ID de firmware atribuída ao MNO ou IHV para o dispositivo. O UUID é codificado com base nas diretrizes da especificação MBIM.
Consulta = InformationBuffer no MBIM_COMMAND_MSG não usado. UUID retornado no InformationBuffer MBIM_COMMAND_DONE.
Definição = Sem suporte.
Evento não solicitado = Sem suporte
Trechos de código para o comportamento do driver UMDF
Conforme indicado anteriormente, o driver UMDF deve indicar ao Windows quando ele inicia e conclui a atualização do firmware. Esta seção fornece trechos de código que mostram como o driver deve notificar o Windows sobre esses eventos.
/**
* 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;
}